<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 6.3.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/xlrblog/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/xlrblog/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/xlrblog/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/xlrblog/images/logo.svg" color="#222">

<link rel="stylesheet" href="/xlrblog/css/main.css">


<link rel="stylesheet" href="/xlrblog/lib/font-awesome/css/all.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"gitee.com","root":"/xlrblog/","scheme":"Pisces","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":true,"show_result":true,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.json"};
  </script>

  <meta name="description" content="SpringBoot开发实用篇2，数据层解决方案，整合第三方技术（缓存，任务，邮件） 数据层解决方案现有数据层解决方案技术选型 Druid + MyBatis-Plus + MySQL  数据源:DruidDataSource 持久化技术:MyBatis-Plus &#x2F; MyBatis 数据库:MySQL  SQL数据源技术数据层技术是每一个企业级应用程序都会用到的，而其中必定会进行数据库">
<meta property="og:type" content="article">
<meta property="og:title" content="SpringBoot实用篇(数据层，缓存，任务，邮件）">
<meta property="og:url" content="https://gitee.com/xlr0306/2023/09/04/SpringBoot%E5%AE%9E%E7%94%A8%E7%AF%87-%E6%95%B0%E6%8D%AE%E5%B1%82%EF%BC%8C%E7%BC%93%E5%AD%98%EF%BC%8C%E4%BB%BB%E5%8A%A1%EF%BC%8C%E9%82%AE%E4%BB%B6%EF%BC%89/index.html">
<meta property="og:site_name" content="君不见的博客">
<meta property="og:description" content="SpringBoot开发实用篇2，数据层解决方案，整合第三方技术（缓存，任务，邮件） 数据层解决方案现有数据层解决方案技术选型 Druid + MyBatis-Plus + MySQL  数据源:DruidDataSource 持久化技术:MyBatis-Plus &#x2F; MyBatis 数据库:MySQL  SQL数据源技术数据层技术是每一个企业级应用程序都会用到的，而其中必定会进行数据库">
<meta property="og:locale" content="zh_CN">
<meta property="article:published_time" content="2023-09-04T02:59:29.000Z">
<meta property="article:modified_time" content="2023-09-04T03:04:59.422Z">
<meta property="article:author" content="君不见">
<meta property="article:tag" content="Spring">
<meta name="twitter:card" content="summary">

<link rel="canonical" href="https://gitee.com/xlr0306/2023/09/04/SpringBoot%E5%AE%9E%E7%94%A8%E7%AF%87-%E6%95%B0%E6%8D%AE%E5%B1%82%EF%BC%8C%E7%BC%93%E5%AD%98%EF%BC%8C%E4%BB%BB%E5%8A%A1%EF%BC%8C%E9%82%AE%E4%BB%B6%EF%BC%89/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true,
    lang   : 'zh-CN'
  };
</script>

  <title>SpringBoot实用篇(数据层，缓存，任务，邮件） | 君不见的博客</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/xlrblog/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">君不见的博客</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
      <p class="site-subtitle" itemprop="description">记录生活中的点点滴滴</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/xlrblog/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/xlrblog/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/xlrblog/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/xlrblog/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a>

  </li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup">
        <div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div id="search-result">
  <div id="no-result">
    <i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>
  </div>
</div>

    </div>
  </div>

</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content post posts-expand">
            

    
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://gitee.com/xlr0306/2023/09/04/SpringBoot%E5%AE%9E%E7%94%A8%E7%AF%87-%E6%95%B0%E6%8D%AE%E5%B1%82%EF%BC%8C%E7%BC%93%E5%AD%98%EF%BC%8C%E4%BB%BB%E5%8A%A1%EF%BC%8C%E9%82%AE%E4%BB%B6%EF%BC%89/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/xlrblog/images/avatar.gif">
      <meta itemprop="name" content="君不见">
      <meta itemprop="description" content="君不见，黄河之水天上来，奔流到海不复回。">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="君不见的博客">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          SpringBoot实用篇(数据层，缓存，任务，邮件）
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2023-09-04 10:59:29 / 修改时间：11:04:59" itemprop="dateCreated datePublished" datetime="2023-09-04T10:59:29+08:00">2023-09-04</time>
            </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/xlrblog/categories/Spring/" itemprop="url" rel="index"><span itemprop="name">Spring</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <p>SpringBoot开发实用篇2，数据层解决方案，整合第三方技术（缓存，任务，邮件）</p>
<h2 id="数据层解决方案"><a href="#数据层解决方案" class="headerlink" title="数据层解决方案"></a>数据层解决方案</h2><p>现有数据层解决方案技术选型</p>
<p>Druid + MyBatis-Plus + MySQL</p>
<blockquote>
<p>数据源:DruidDataSource</p>
<p>持久化技术:MyBatis-Plus &#x2F; MyBatis</p>
<p>数据库:MySQL</p>
</blockquote>
<h3 id="SQL"><a href="#SQL" class="headerlink" title="SQL"></a>SQL</h3><h4 id="数据源技术"><a href="#数据源技术" class="headerlink" title="数据源技术"></a>数据源技术</h4><p>数据层技术是每一个企业级应用程序都会用到的，而其中必定会进行数据库连接的管理。springboot根据开发者的习惯出发，开发者提供了数据源技术，就用开发者提供的，开发者没有提供就用默认的。</p>
<p>springboot提供了3款内嵌数据源技术：</p>
<ul>
<li><p>HikariCP</p>
<p>这是springboot官方推荐的数据源技术，作为默认内置数据源使用。不配置数据源，默认用这个。</p>
</li>
<li><p>Tomcat提供DataSource</p>
<p>Tomcat提供的DataSource，如果不想用HikartCP，并且使用tomcat作为web服务器进行web程序的开发，使用这个。为什么是Tomcat，不是其他web服务器呢？因为web技术导入starter后，默认使用内嵌tomcat，既然都是默认使用的技术了，那就一用到底，数据源也用它的。怎么才能不使用HikartCP用tomcat提供的默认数据源对象呢？把HikartCP技术的坐标排除掉就OK了。</p>
</li>
<li><p>Commons DBCP</p>
<p>DBCP，这个使用的条件就更苛刻了，既不使用HikartCP也不使用tomcat的DataSource时，默认用这个。</p>
</li>
</ul>
<p>之前我们配置druid时使用druid的starter对应的配置如下：</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">datasource:</span></span><br><span class="line">    <span class="attr">druid:</span>	</span><br><span class="line">   	  <span class="attr">url:</span> <span class="string">jdbc:mysql://localhost:3306/db1?serverTimezone=UTC</span></span><br><span class="line">      <span class="attr">driver-class-name:</span> <span class="string">com.mysql.cj.jdbc.Driver</span></span><br><span class="line">      <span class="attr">username:</span> <span class="string">root</span></span><br><span class="line">      <span class="attr">password:</span> <span class="string">root</span></span><br></pre></td></tr></table></figure>

<p>换成是默认的数据源HikariCP后，直接吧druid删掉就行了，如下：</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">datasource:</span></span><br><span class="line">    <span class="attr">url:</span> <span class="string">jdbc:mysql://localhost:3306/db1?serverTimezone=UTC</span></span><br><span class="line">    <span class="attr">driver-class-name:</span> <span class="string">com.mysql.cj.jdbc.Driver</span></span><br><span class="line">    <span class="attr">username:</span> <span class="string">root</span></span><br><span class="line">    <span class="attr">password:</span> <span class="string">root</span></span><br></pre></td></tr></table></figure>

<p>当然，也可以写上是对hikari做的配置，但是url地址要单独配置，如下：</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">datasource:</span></span><br><span class="line">    <span class="attr">url:</span> <span class="string">jdbc:mysql://localhost:3306/db1?useSSL=false</span></span><br><span class="line">    <span class="attr">hikari:</span></span><br><span class="line">      <span class="attr">driver-class-name:</span> <span class="string">com.mysql.cj.jdbc.Driver</span></span><br><span class="line">      <span class="attr">username:</span> <span class="string">root</span></span><br><span class="line">      <span class="attr">password:</span> <span class="string">&quot;031006&quot;</span></span><br></pre></td></tr></table></figure>

<p><strong>总结</strong></p>
<ol>
<li>springboot技术提供了3种内置的数据源技术，分别是Hikari、tomcat内置数据源、DBCP</li>
</ol>
<h4 id="持久化技术"><a href="#持久化技术" class="headerlink" title="持久化技术"></a>持久化技术</h4><p>springboot给开发者提供了一套现成的数据层技术，叫做JdbcTemplate。其实这个技术是spring技术提供的，所以在springboot技术范畴中，这个技术也是存在的，毕竟springboot技术是加速spring程序开发而创建的。</p>
<p><strong>步骤①</strong>：导入jdbc对应的坐标，记得是starter</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-jdbc<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">&lt;/dependency</span><br></pre></td></tr></table></figure>

<p><strong>步骤②</strong>：自动装配JdbcTemplate对象</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@SpringBootTest</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">DaoTest</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> JdbcTemplate jdbcTemplate;</span><br></pre></td></tr></table></figure>

<p><strong>步骤③</strong>：使用JdbcTemplate实现查询操作（非实体类封装数据的查询操作）</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">testJdbcTemplate</span><span class="params">(<span class="meta">@Autowired</span> JdbcTemplate jdbcTemplate)</span>&#123;</span><br><span class="line">    <span class="type">String</span> <span class="variable">sql</span> <span class="operator">=</span> <span class="string">&quot;select * from tbl_book&quot;</span>;</span><br><span class="line">    List&lt;Map&lt;String, Object&gt;&gt; maps = jdbcTemplate.queryForList(sql);</span><br><span class="line">    System.out.println(maps);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>步骤④</strong>：使用JdbcTemplate实现查询操作（实体类封装数据的查询操作）</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">testJdbcTemplate</span><span class="params">()</span> &#123;</span><br><span class="line"></span><br><span class="line"><span class="comment">//        String sql = &quot;select * from tbl_book where id = 5&quot;;</span></span><br><span class="line">        <span class="type">String</span> <span class="variable">sql</span> <span class="operator">=</span> <span class="string">&quot;select * from tbl_book&quot;</span>;</span><br><span class="line"><span class="comment">//        List&lt;Map&lt;String, Object&gt;&gt; maps = jdbcTemplate.queryForList(sql);</span></span><br><span class="line"><span class="comment">//        System.out.println(maps);</span></span><br><span class="line">        RowMapper&lt;Book&gt; rm = <span class="keyword">new</span> <span class="title class_">RowMapper</span>&lt;Book&gt;() &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="keyword">public</span> Book <span class="title function_">mapRow</span><span class="params">(ResultSet rs, <span class="type">int</span> rowNum)</span> <span class="keyword">throws</span> SQLException &#123;</span><br><span class="line">                <span class="type">int</span> <span class="variable">id</span> <span class="operator">=</span> rs.getInt(<span class="string">&quot;id&quot;</span>);</span><br><span class="line">                <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> rs.getString(<span class="string">&quot;name&quot;</span>);</span><br><span class="line">                <span class="type">String</span> <span class="variable">type</span> <span class="operator">=</span> rs.getString(<span class="string">&quot;type&quot;</span>);</span><br><span class="line">                <span class="type">String</span> <span class="variable">description</span> <span class="operator">=</span> rs.getString(<span class="string">&quot;description&quot;</span>);</span><br><span class="line"></span><br><span class="line">                <span class="type">Book</span> <span class="variable">book</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Book</span>();</span><br><span class="line">                book.setId(id);</span><br><span class="line">                book.setType(type);</span><br><span class="line">                book.setName(name);</span><br><span class="line">                book.setDescription(description);</span><br><span class="line"></span><br><span class="line">                <span class="keyword">return</span> book;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;;</span><br><span class="line">        List&lt;Book&gt; books = jdbcTemplate.query(sql,rm);</span><br><span class="line">        System.out.println(books);</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<p><strong>步骤⑤</strong>：使用JdbcTemplate实现增删改操作</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">testJdbcTemplateInsert</span><span class="params">()</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="type">String</span> <span class="variable">sql</span> <span class="operator">=</span> <span class="string">&quot;insert into tbl_book value(null,&#x27;SpringBoot&#x27;,&#x27;Spring&#x27;,&#x27;SpringBoot2&#x27;)&quot;</span>;</span><br><span class="line">    <span class="type">int</span> <span class="variable">update</span> <span class="operator">=</span> jdbcTemplate.update(sql);</span><br><span class="line">    System.out.println(update);</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>如果想对JdbcTemplate对象进行相关配置，可以在yml文件中进行设定	</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">datasource:</span></span><br><span class="line">    <span class="attr">url:</span> <span class="string">jdbc:mysql://localhost:3306/db1?useSSL=false</span></span><br><span class="line">    <span class="attr">hikari:</span></span><br><span class="line">      <span class="attr">driver-class-name:</span> <span class="string">com.mysql.cj.jdbc.Driver</span></span><br><span class="line">      <span class="attr">username:</span> <span class="string">root</span></span><br><span class="line">      <span class="attr">password:</span> <span class="string">&quot;031006&quot;</span></span><br><span class="line">  <span class="attr">jdbc:</span></span><br><span class="line">    <span class="attr">template:</span></span><br><span class="line">      <span class="attr">query-timeout:</span> <span class="number">2000</span> <span class="comment"># 查询超时时间</span></span><br><span class="line">      <span class="attr">max-rows:</span> <span class="number">500</span> <span class="comment"># 最大行数</span></span><br><span class="line">      <span class="attr">fetch-size:</span> <span class="number">50</span> <span class="comment"># 缓存行数</span></span><br></pre></td></tr></table></figure>

<p><strong>总结</strong></p>
<ol>
<li>SpringBoot内置JdbcTemplate持久化解决方案</li>
<li>使用JdbcTemplate需要导入spring-boot-starter-jdbc的坐标</li>
</ol>
<h4 id="数据库技术"><a href="#数据库技术" class="headerlink" title="数据库技术"></a>数据库技术</h4><p>截止到目前，springboot给开发者提供了内置的<strong>数据源解决方案</strong>和<strong>持久化解决方案</strong>，springboot也提供有内置的<strong>数据库解决方案</strong></p>
<p>springboot提供了3款内置的数据库，分别是</p>
<ul>
<li>H2</li>
<li>HSQL</li>
<li>Derby</li>
</ul>
<p>以上三款数据库除了可以独立安装之外，还可以像是tomcat服务器一样，采用内嵌的形式运行在springboot容器中。这三款数据库底层都是使用java语言开发的。</p>
<p><strong>步骤①</strong>：导入H2数据库对应的坐标，一共2个</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.h2database<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>h2<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-data-jpa<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p><strong>步骤②</strong>：将工程设置为web工程，启动工程时启动H2数据库</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-web<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p><strong>步骤③</strong>：通过配置开启H2数据库控制台访问程序，也可以使用其他的数据库连接软件操作</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">h2:</span></span><br><span class="line">    <span class="attr">console:</span></span><br><span class="line">      <span class="attr">enabled:</span> <span class="literal">true</span></span><br><span class="line">      <span class="attr">path:</span> <span class="string">/h2</span></span><br></pre></td></tr></table></figure>

<p>web端访问路径&#x2F;h2，访问密码<strong>123456</strong>，如果访问失败，先配置下列数据源，启动程序运行后再次访问&#x2F;h2路径就可以正常访问了</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">datasource:</span></span><br><span class="line">  <span class="attr">url:</span> <span class="string">jdbc:h2:~/test</span></span><br><span class="line">  <span class="attr">hikari:</span></span><br><span class="line">    <span class="attr">driver-class-name:</span> <span class="string">org.h2.Driver</span></span><br><span class="line">    <span class="attr">username:</span> <span class="string">sa</span></span><br><span class="line">    <span class="attr">password:</span> <span class="number">123456</span></span><br></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">create</span> <span class="keyword">table</span> tbl_book (id <span class="type">int</span>,type <span class="type">varchar</span> ,name <span class="type">varchar</span> ,description <span class="type">varchar</span>)</span><br></pre></td></tr></table></figure>

<p><strong>步骤④</strong>：使用JdbcTemplate或MyBatisPlus技术操作数据库</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> JdbcTemplate jdbcTemplate;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">testJdbcTemplate</span><span class="params">()</span> &#123;</span><br><span class="line"></span><br><span class="line"><span class="comment">//        String sql = &quot;select * from tbl_book where id = 5&quot;;</span></span><br><span class="line">        <span class="type">String</span> <span class="variable">sql</span> <span class="operator">=</span> <span class="string">&quot;select * from tbl_book&quot;</span>;</span><br><span class="line"><span class="comment">//        List&lt;Map&lt;String, Object&gt;&gt; maps = jdbcTemplate.queryForList(sql);</span></span><br><span class="line"><span class="comment">//        System.out.println(maps);</span></span><br><span class="line">        RowMapper&lt;Book&gt; rm = <span class="keyword">new</span> <span class="title class_">RowMapper</span>&lt;Book&gt;() &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="keyword">public</span> Book <span class="title function_">mapRow</span><span class="params">(ResultSet rs, <span class="type">int</span> rowNum)</span> <span class="keyword">throws</span> SQLException &#123;</span><br><span class="line">                <span class="type">int</span> <span class="variable">id</span> <span class="operator">=</span> rs.getInt(<span class="string">&quot;id&quot;</span>);</span><br><span class="line">                <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> rs.getString(<span class="string">&quot;name&quot;</span>);</span><br><span class="line">                <span class="type">String</span> <span class="variable">type</span> <span class="operator">=</span> rs.getString(<span class="string">&quot;type&quot;</span>);</span><br><span class="line">                <span class="type">String</span> <span class="variable">description</span> <span class="operator">=</span> rs.getString(<span class="string">&quot;description&quot;</span>);</span><br><span class="line"></span><br><span class="line">                <span class="type">Book</span> <span class="variable">book</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Book</span>();</span><br><span class="line">                book.setId(id);</span><br><span class="line">                book.setType(type);</span><br><span class="line">                book.setName(name);</span><br><span class="line">                book.setDescription(description);</span><br><span class="line"></span><br><span class="line">                <span class="keyword">return</span> book;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;;</span><br><span class="line">        List&lt;Book&gt; books = jdbcTemplate.query(sql,rm);</span><br><span class="line">        System.out.println(books);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">testJdbcTemplateInsert</span><span class="params">()</span> &#123;</span><br><span class="line"></span><br><span class="line">        <span class="type">String</span> <span class="variable">sql</span> <span class="operator">=</span> <span class="string">&quot;insert into tbl_book values(2,&#x27;SpringBoot&#x27;,&#x27;Spring&#x27;,&#x27;SpringBoot2&#x27;)&quot;</span>;</span><br><span class="line">        <span class="type">int</span> <span class="variable">update</span> <span class="operator">=</span> jdbcTemplate.update(sql);</span><br><span class="line">        System.out.println(update);</span><br><span class="line"></span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<p><strong>总结</strong></p>
<ol>
<li>H2内嵌式数据库启动方式，添加坐标，添加配置</li>
<li>H2数据库线上运行时请务必关闭</li>
</ol>
<h3 id="NoSQL"><a href="#NoSQL" class="headerlink" title="NoSQL"></a>NoSQL</h3><p>NoSQL就是非关系型数据库解决方案，意思就是数据该存存该取取，只是这些数据不放在关系型数据库中了。</p>
<h4 id="SpringBoot整合Redis"><a href="#SpringBoot整合Redis" class="headerlink" title="SpringBoot整合Redis"></a>SpringBoot整合Redis</h4><p>Redis是一款key-value存储结构的内存级NoSQL数据库</p>
<ul>
<li><p>支持多种数据存储格式</p>
<p>可以直接存字符串，也可以存一个map集合，list集合</p>
</li>
<li><p>支持持久化</p>
</li>
<li><p>支持集群</p>
</li>
</ul>
<h5 id="启动服务器"><a href="#启动服务器" class="headerlink" title="启动服务器"></a><strong>启动服务器</strong></h5><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">redis-server.exe redis.windows.conf</span><br></pre></td></tr></table></figure>

<p>服务器对外服务端口，默认6379。</p>
<h5 id="启动客户端"><a href="#启动客户端" class="headerlink" title="启动客户端"></a><strong>启动客户端</strong></h5><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">redis-cli.exe</span><br></pre></td></tr></table></figure>

<p>如果启动redis服务器失败，可以先启动客户端，然后执行shutdown操作后退出，此时redis服务器就可以正常执行了。</p>
<h5 id="基本操作"><a href="#基本操作" class="headerlink" title="基本操作"></a>基本操作</h5><p>服务器启动后，使用客户端就可以连接服务器，类似于启动完MySQL数据库，然后启动SQL命令行操作数据库。		</p>
<p>放置一个字符串数据到redis中，先为数据定义一个名称，比如name,age等，然后使用命令set设置数据到redis服务器中即可</p>
<figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">set</span> name faiz</span><br><span class="line"><span class="built_in">set</span> age <span class="number">18</span></span><br></pre></td></tr></table></figure>

<p>从redis中取出已经放入的数据，根据名称取，就可以得到对应数据。如果没有对应数据就会得到(nil)</p>
<figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">get name</span><br><span class="line">get age</span><br></pre></td></tr></table></figure>

<p>以上使用的数据存储是一个名称对应一个值，如果要维护的数据过多，可以使用别的数据存储结构。例如hash，它是一种一个名称下可以存储多个数据的存储模型，并且每个数据也可以有自己的二级存储名称。向hash结构中存储数据格式如下：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">hset a a1 aa1		#对外key名称是a，在名称为a的存储模型中，a1这个key中保存了数据aa1</span><br><span class="line">hset a a2 aa2</span><br></pre></td></tr></table></figure>

<p>获取hash结构中的数据命令如下</p>
<figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">hget a a1			#得到aa1</span><br><span class="line">hget a a2			#得到aa2</span><br></pre></td></tr></table></figure>

<h5 id="整合"><a href="#整合" class="headerlink" title="整合"></a><strong>整合</strong></h5><p>springboot整合任何技术其实就是在springboot中使用对应技术的API。</p>
<p><strong>步骤①</strong>：导入springboot整合redis的starter坐标</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-data-redis<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>上述坐标可以在创建模块的时候通过勾选的形式进行选择，归属NoSQL分类中,选择<code>Spring Data Redis (Access+Driver)</code></p>
<p><strong>步骤②</strong>：进行基础配置</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">redis:</span></span><br><span class="line">    <span class="attr">host:</span> <span class="string">localhost</span></span><br><span class="line">    <span class="attr">port:</span> <span class="number">6379</span></span><br></pre></td></tr></table></figure>

<p>​	操作redis，最基本的信息就是操作哪一台redis服务器，所以服务器地址属于基础配置信息，不可缺少。但是以上两组信息都有默认配置，刚好就是上述配置值。</p>
<p><strong>步骤③</strong>：使用springboot整合redis的专用客户端接口操作，此处使用的是RedisTemplate</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.example;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> org.junit.jupiter.api.Test;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.boot.test.context.SpringBootTest;</span><br><span class="line"><span class="keyword">import</span> org.springframework.data.redis.core.HashOperations;</span><br><span class="line"><span class="keyword">import</span> org.springframework.data.redis.core.RedisTemplate;</span><br><span class="line"><span class="keyword">import</span> org.springframework.data.redis.core.ValueOperations;</span><br><span class="line"></span><br><span class="line"><span class="meta">@SpringBootTest</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Springboot05RedisApplicationTests</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> RedisTemplate redisTemplate;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">testRedisSet</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="type">ValueOperations</span> <span class="variable">ops</span> <span class="operator">=</span> redisTemplate.opsForValue();</span><br><span class="line">        ops.set(<span class="string">&quot;name&quot;</span>, <span class="string">&quot;faiz&quot;</span>);</span><br><span class="line">        ops.set(<span class="string">&quot;age&quot;</span>, <span class="number">18</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">testRedisGet</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="type">ValueOperations</span> <span class="variable">ops</span> <span class="operator">=</span> redisTemplate.opsForValue();</span><br><span class="line">        <span class="type">Object</span> <span class="variable">name</span> <span class="operator">=</span> ops.get(<span class="string">&quot;name&quot;</span>);</span><br><span class="line">        <span class="type">Object</span> <span class="variable">age</span> <span class="operator">=</span> ops.get(<span class="string">&quot;age&quot;</span>);</span><br><span class="line">        System.out.println(name);</span><br><span class="line">        System.out.println(age);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">testRedisHset</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="type">HashOperations</span> <span class="variable">ops</span> <span class="operator">=</span> redisTemplate.opsForHash();</span><br><span class="line">        ops.put(<span class="string">&quot;info&quot;</span>, <span class="string">&quot;name&quot;</span>, <span class="string">&quot;faiz555&quot;</span>);</span><br><span class="line">        ops.put(<span class="string">&quot;info&quot;</span>, <span class="string">&quot;age&quot;</span>, <span class="number">555</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">testRedisHget</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="type">HashOperations</span> <span class="variable">ops</span> <span class="operator">=</span> redisTemplate.opsForHash();</span><br><span class="line">        <span class="type">Object</span> <span class="variable">name</span> <span class="operator">=</span> ops.get(<span class="string">&quot;info&quot;</span>, <span class="string">&quot;name&quot;</span>);</span><br><span class="line">        <span class="type">Object</span> <span class="variable">age</span> <span class="operator">=</span> ops.get(<span class="string">&quot;info&quot;</span>, <span class="string">&quot;age&quot;</span>);</span><br><span class="line">        System.out.println(name);</span><br><span class="line">        System.out.println(age);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>在操作redis时，需要先确认操作何种数据，根据数据种类得到操作接口。例如使用opsForValue()获取string类型的数据操作接口，使用opsForHash()获取hash类型的数据操作接口，剩下的就是调用对应api操作了。</p>
<p><strong>StringRedisTemplate</strong></p>
<p>由于redis内部不提供java对象的存储格式，因此当操作的数据以对象的形式存在时，会进行转码，转换成字符串格式后进行操作。为了方便开发者使用基于字符串为数据的操作，springboot整合redis时提供了专用的API接口StringRedisTemplate，可以理解为这是RedisTemplate的一种指定数据泛型的操作API。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@SpringBootTest</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">StringRedisTemplateTest</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> StringRedisTemplate stringRedisTemplate;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">testRedisGet</span><span class="params">()</span> &#123;</span><br><span class="line">        ValueOperations&lt;String, String&gt; ops = stringRedisTemplate.opsForValue();</span><br><span class="line">        <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> ops.get(<span class="string">&quot;name&quot;</span>);</span><br><span class="line">        System.out.println(name);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>redis客户端选择</strong></p>
<p> springboot整合redis技术提供了多种客户端兼容模式，默认提供的是lettucs客户端技术，也可以根据需要切换成指定客户端技术，例如jedis客户端技术，切换成jedis客户端技术操作步骤如下：</p>
<p><strong>步骤①</strong>：导入jedis坐标</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>redis.clients<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>jedis<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>jedis坐标受springboot管理，无需提供版本号</p>
<p><strong>步骤②</strong>：配置客户端技术类型，设置为jedis</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">redis:</span></span><br><span class="line">    <span class="attr">host:</span> <span class="string">localhost</span></span><br><span class="line">    <span class="attr">port:</span> <span class="number">6379</span></span><br><span class="line">    <span class="attr">client-type:</span> <span class="string">jedis</span></span><br></pre></td></tr></table></figure>

<p><strong>步骤③</strong>：根据需要设置对应的配置</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">redis:</span></span><br><span class="line">    <span class="attr">host:</span> <span class="string">localhost</span></span><br><span class="line">    <span class="attr">port:</span> <span class="number">6379</span></span><br><span class="line">    <span class="attr">client-type:</span> <span class="string">jedis</span></span><br><span class="line">    <span class="attr">lettuce:</span></span><br><span class="line">      <span class="attr">pool:</span></span><br><span class="line">        <span class="attr">max-active:</span> <span class="number">16</span></span><br><span class="line">    <span class="attr">jedis:</span></span><br><span class="line">      <span class="attr">pool:</span></span><br><span class="line">        <span class="attr">max-active:</span> <span class="number">16</span></span><br></pre></td></tr></table></figure>

<p><strong>lettcus与jedis区别</strong></p>
<ul>
<li>jedis连接Redis服务器是直连模式，当多线程模式下使用jedis会存在线程安全问题，解决方案可以通过配置连接池使每个连接专用，这样整体性能就大受影响</li>
<li>lettcus基于Netty框架进行与Redis服务器连接，底层设计中采用StatefulRedisConnection。 StatefulRedisConnection自身是线程安全的，可以保障并发访问安全问题，所以一个连接可以被多线程复用。当然lettcus也支持多连接实例一起工作</li>
</ul>
<h4 id="SpringBoot整合MongoDB"><a href="#SpringBoot整合MongoDB" class="headerlink" title="SpringBoot整合MongoDB"></a>SpringBoot整合MongoDB</h4><p>MongoDB是一个开源、高性能、无模式的文档型数据库，它是NoSQL数据库产品中的一种，是最像关系型数据库的非关系型数据库。</p>
<p>什么叫无模式呢？简单说就是作为一款数据库，没有固定的数据存储结构，第一条数据可能有A、B、C一共3个字段，第二条数据可能有D、E、F也是3个字段，第三条数据可能是A、C、E3个字段，也就是说数据的结构不固定，这就是无模式。</p>
<p>windows版安装包下载地址：<a target="_blank" rel="noopener" href="https://www.mongodb.com/try/download">https://www.mongodb.com/try/download</a></p>
<h5 id="启动服务器-1"><a href="#启动服务器-1" class="headerlink" title="启动服务器"></a><strong>启动服务器</strong></h5><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mongod --dbpath=..\data\db</span><br></pre></td></tr></table></figure>

<p>启动服务器时需要指定数据存储位置，通过参数–dbpath进行设置，可以根据需要自行设置数据存储路径。默认服务端口27017。</p>
<h5 id="启动客户端-1"><a href="#启动客户端-1" class="headerlink" title="启动客户端"></a><strong>启动客户端</strong></h5><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mongo --host=<span class="number">127</span>.<span class="number">0</span>.<span class="number">0</span>.<span class="number">1</span> --port=<span class="number">27017</span></span><br></pre></td></tr></table></figure>

<h5 id="基本操作-1"><a href="#基本操作-1" class="headerlink" title="基本操作"></a><strong>基本操作</strong></h5><p>新增文档：（文档是一种类似json格式的数据，初学者可以先把数据理解为就是json数据）	</p>
<figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">db.集合名称.insert/save/insertOne(文档)</span><br></pre></td></tr></table></figure>

<p>删除文档：</p>
<figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">db.集合名称.remove(条件)</span><br></pre></td></tr></table></figure>

<p>修改文档：</p>
<figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">db.集合名称.update(条件，&#123;操作种类:&#123;文档&#125;&#125;)</span><br></pre></td></tr></table></figure>

<p>查询文档：</p>
<figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">基础查询</span><br><span class="line">查询全部：		   db.集合.<span class="built_in">find</span>();</span><br><span class="line">查第一条：		   db.集合.findOne()</span><br><span class="line">查询指定数量文档：	db.集合.<span class="built_in">find</span>().limit(<span class="number">10</span>)					//查<span class="number">10</span>条文档</span><br><span class="line">跳过指定数量文档：	db.集合.<span class="built_in">find</span>().skip(<span class="number">20</span>)					//跳过<span class="number">20</span>条文档</span><br><span class="line">统计：			  	db.集合.count()</span><br><span class="line">排序：				db.集合.<span class="built_in">sort</span>(&#123;age:<span class="number">1</span>&#125;)						//按age升序排序</span><br><span class="line">投影：				db.集合名称.<span class="built_in">find</span>(条件,&#123;name:<span class="number">1</span>,age:<span class="number">1</span>&#125;)		 //仅保留name与age域</span><br><span class="line"></span><br><span class="line">条件查询</span><br><span class="line">基本格式：			db.集合.<span class="built_in">find</span>(&#123;条件&#125;)</span><br><span class="line">模糊查询：			db.集合.<span class="built_in">find</span>(&#123;域名:/正则表达式/&#125;)		  //等同SQL中的like，比like强大，可以执行正则所有规则</span><br><span class="line">条件比较运算：		   db.集合.<span class="built_in">find</span>(&#123;域名:&#123;$gt:值&#125;&#125;)				//等同SQL中的数值比较操作，例如：name&gt;<span class="number">18</span></span><br><span class="line">包含查询：			db.集合.<span class="built_in">find</span>(&#123;域名:&#123;$<span class="keyword">in</span>:[值<span class="number">1</span>，值<span class="number">2</span>]&#125;&#125;)		//等同于SQL中的<span class="keyword">in</span></span><br><span class="line">条件连接查询：		   db.集合.<span class="built_in">find</span>(&#123;$and:[&#123;条件<span class="number">1</span>&#125;,&#123;条件<span class="number">2</span>&#125;]&#125;)	   //等同于SQL中的and、or</span><br></pre></td></tr></table></figure>

<figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">//添加文档</span><br><span class="line">db.book.save(&#123;&quot;name&quot;:&quot;SpringBoot&quot;&#125;)</span><br><span class="line">db.book.save(&#123;&quot;name&quot;:&quot;SpringBoot&quot;,<span class="built_in">type</span>:&quot;Spring&quot;&#125;)</span><br><span class="line"></span><br><span class="line">//查询</span><br><span class="line">db.book.<span class="built_in">find</span>()</span><br><span class="line">db.book.<span class="built_in">find</span>(&#123;<span class="built_in">type</span>:&quot;Spring&quot;&#125;)</span><br><span class="line"></span><br><span class="line">//删除操作</span><br><span class="line">db.book.remove(&#123;<span class="built_in">type</span>:&quot;Spring&quot;&#125;)</span><br><span class="line"></span><br><span class="line">//修改操作</span><br><span class="line">db.book.update(&#123;name:&quot;SpringBoot&quot;&#125;,&#123;$<span class="built_in">set</span>:&#123;name:&quot;SpringBoot2&quot;&#125;&#125;)</span><br><span class="line">db.book.updateMany(&#123;name:&quot;SpringBoot&quot;&#125;,&#123;$<span class="built_in">set</span>:&#123;name:&quot;SpringBoot2&quot;&#125;&#125;)</span><br></pre></td></tr></table></figure>

<h5 id="整合-1"><a href="#整合-1" class="headerlink" title="整合"></a><strong>整合</strong></h5><p><strong>步骤①</strong>：导入springboot整合MongoDB的starter坐标</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-data-mongodb<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>上述坐标也可以在创建模块的时候通过勾选的形式进行选择<code>Spring Data MongoDB</code>，同样归属NoSQL分类中</p>
<p><strong>步骤②</strong>：进行基础配置</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">data:</span></span><br><span class="line">    <span class="attr">mongodb:</span></span><br><span class="line">      <span class="attr">uri:</span> <span class="string">mongodb://localhost/itheima</span></span><br></pre></td></tr></table></figure>

<p><strong>步骤③</strong>：使用springboot整合MongoDB的专用客户端接口MongoTemplate来进行操作</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.example;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.example.domain.Book;</span><br><span class="line"><span class="keyword">import</span> org.junit.jupiter.api.Test;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.boot.test.context.SpringBootTest;</span><br><span class="line"><span class="keyword">import</span> org.springframework.data.mongodb.core.MongoTemplate;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.List;</span><br><span class="line"></span><br><span class="line"><span class="meta">@SpringBootTest</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Springboot06MongodbApplicationTests</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> MongoTemplate mongoTemplate;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">testMongoSave</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="type">Book</span> <span class="variable">book</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Book</span>();</span><br><span class="line">        book.setId(<span class="number">5</span>);</span><br><span class="line">        book.setName(<span class="string">&quot;SpringBootStudy&quot;</span>);</span><br><span class="line">        book.setType(<span class="string">&quot;SpringBoot&quot;</span>);</span><br><span class="line">        book.setDescription(<span class="string">&quot;Everything is possible!&quot;</span>);</span><br><span class="line">        mongoTemplate.save(book);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">testMongoFind</span><span class="params">()</span> &#123;</span><br><span class="line">        List&lt;Book&gt; books = mongoTemplate.findAll(Book.class);</span><br><span class="line">        System.out.println(books);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>总结</strong></p>
<ol>
<li>springboot整合MongoDB步骤<ol>
<li>导入springboot整合MongoDB的starter坐标</li>
<li>进行基础配置</li>
<li>使用springboot整合MongoDB的专用客户端接口MongoTemplate操作</li>
</ol>
</li>
</ol>
<h4 id="SpringBoot整合ES"><a href="#SpringBoot整合ES" class="headerlink" title="SpringBoot整合ES"></a>SpringBoot整合ES</h4><p>ES（Elasticsearch）是一个分布式全文搜索引擎，重点是全文搜索。</p>
<h5 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h5><p>windows版安装包下载地址：<a target="_blank" rel="noopener" href="https://www.elastic.co/cn/downloads/elasticsearch">https:&#x2F;&#x2F;</a><a target="_blank" rel="noopener" href="https://www.elastic.co/cn/downloads/elasticsearch">www.elastic.co/cn/downloads/elasticsearch</a></p>
<p>下载的安装包是解压缩就能使用的zip文件，解压缩完毕后会得到如下文件</p>
<ul>
<li>bin目录：包含所有的可执行命令</li>
<li>config目录：包含ES服务器使用的配置文件</li>
<li>jdk目录：此目录中包含了一个完整的jdk工具包，版本17，当ES升级时，使用最新版本的jdk确保不会出现版本支持性不足的问题</li>
<li>lib目录：包含ES运行的依赖jar文件</li>
<li>logs目录：包含ES运行后产生的所有日志文件</li>
<li>modules目录：包含ES软件中所有的功能模块，也是一个一个的jar包。和jar目录不同，jar目录是ES运行期间依赖的jar包，modules是ES软件自己的功能jar包</li>
<li>plugins目录：包含ES软件安装的插件，默认为空</li>
</ul>
<h5 id="启动服务器-2"><a href="#启动服务器-2" class="headerlink" title="启动服务器"></a><strong>启动服务器</strong></h5><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">elasticsearch.bat</span><br></pre></td></tr></table></figure>

<p>双击elasticsearch.bat文件即可启动ES服务器，默认服务端口9200。通过浏览器访问<a href="http://localhost:9200看到如下信息视为ES服务器正常启动">http://localhost:9200看到如下信息视为ES服务器正常启动</a></p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;name&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;LAPTOP-4TKGHM3T&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;cluster_name&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;elasticsearch&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;cluster_uuid&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;RABCtWJFTdmPMTEyCsdEAg&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;version&quot;</span> <span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;number&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;7.16.2&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;build_flavor&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;default&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;build_type&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;zip&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;build_hash&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;2b937c44140b6559905130a8650c64dbd0879cfb&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;build_date&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;2021-12-18T19:42:46.604893745Z&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;build_snapshot&quot;</span> <span class="punctuation">:</span> <span class="literal"><span class="keyword">false</span></span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;lucene_version&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;8.10.1&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;minimum_wire_compatibility_version&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;6.8.0&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;minimum_index_compatibility_version&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;6.0.0-beta1&quot;</span></span><br><span class="line">  <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;tagline&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;You Know, for Search&quot;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure>

<h5 id="基本操作-2"><a href="#基本操作-2" class="headerlink" title="基本操作"></a>基本操作</h5><p>ES中保存有我们要查询的数据，只不过格式和数据库存储数据格式不同而已。在ES中我们要先创建倒排索引，这个索引的功能又点类似于数据库的表，然后将数据添加到倒排索引中，添加的数据称为文档。所以要进行ES的操作要先创建索引，再添加文档，这样才能进行后续的查询操作。</p>
<p>要操作ES可以通过Rest风格的请求来进行，也就是说发送一个请求就可以执行一个操作。比如新建索引，删除索引这些操作都可以使用发送请求的形式来进行。</p>
<ul>
<li><p>创建索引，books是索引名称，下同</p>
<figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">PUT请求		http://localhost:<span class="number">9200</span>/books</span><br></pre></td></tr></table></figure>

<p>发送请求后，看到如下信息即索引创建成功</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;acknowledged&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;shards_acknowledged&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;index&quot;</span><span class="punctuation">:</span> <span class="string">&quot;books&quot;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure>

<p>重复创建已经存在的索引会出现错误信息，reason属性中描述错误原因</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;error&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;root_cause&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">            <span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;resource_already_exists_exception&quot;</span><span class="punctuation">,</span></span><br><span class="line">                <span class="attr">&quot;reason&quot;</span><span class="punctuation">:</span> <span class="string">&quot;index [books/VgC_XMVAQmedaiBNSgO2-w] already exists&quot;</span><span class="punctuation">,</span></span><br><span class="line">                <span class="attr">&quot;index_uuid&quot;</span><span class="punctuation">:</span> <span class="string">&quot;VgC_XMVAQmedaiBNSgO2-w&quot;</span><span class="punctuation">,</span></span><br><span class="line">                <span class="attr">&quot;index&quot;</span><span class="punctuation">:</span> <span class="string">&quot;books&quot;</span></span><br><span class="line">            <span class="punctuation">&#125;</span></span><br><span class="line">        <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;resource_already_exists_exception&quot;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;reason&quot;</span><span class="punctuation">:</span> <span class="string">&quot;index [books/VgC_XMVAQmedaiBNSgO2-w] already exists&quot;</span><span class="punctuation">,</span>	# books索引已经存在</span><br><span class="line">        <span class="attr">&quot;index_uuid&quot;</span><span class="punctuation">:</span> <span class="string">&quot;VgC_XMVAQmedaiBNSgO2-w&quot;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;index&quot;</span><span class="punctuation">:</span> <span class="string">&quot;book&quot;</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;status&quot;</span><span class="punctuation">:</span> <span class="number">400</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>查询索引</p>
<figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">GET请求		http://localhost:<span class="number">9200</span>/books</span><br></pre></td></tr></table></figure>

<p>查询索引得到索引相关信息，如下</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;book&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;aliases&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span><span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;mappings&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span><span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;settings&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;index&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;routing&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                    <span class="attr">&quot;allocation&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                        <span class="attr">&quot;include&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                            <span class="attr">&quot;_tier_preference&quot;</span><span class="punctuation">:</span> <span class="string">&quot;data_content&quot;</span></span><br><span class="line">                        <span class="punctuation">&#125;</span></span><br><span class="line">                    <span class="punctuation">&#125;</span></span><br><span class="line">                <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">                <span class="attr">&quot;number_of_shards&quot;</span><span class="punctuation">:</span> <span class="string">&quot;1&quot;</span><span class="punctuation">,</span></span><br><span class="line">                <span class="attr">&quot;provided_name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;books&quot;</span><span class="punctuation">,</span></span><br><span class="line">                <span class="attr">&quot;creation_date&quot;</span><span class="punctuation">:</span> <span class="string">&quot;1645768584849&quot;</span><span class="punctuation">,</span></span><br><span class="line">                <span class="attr">&quot;number_of_replicas&quot;</span><span class="punctuation">:</span> <span class="string">&quot;1&quot;</span><span class="punctuation">,</span></span><br><span class="line">                <span class="attr">&quot;uuid&quot;</span><span class="punctuation">:</span> <span class="string">&quot;VgC_XMVAQmedaiBNSgO2-w&quot;</span><span class="punctuation">,</span></span><br><span class="line">                <span class="attr">&quot;version&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                    <span class="attr">&quot;created&quot;</span><span class="punctuation">:</span> <span class="string">&quot;7160299&quot;</span></span><br><span class="line">                <span class="punctuation">&#125;</span></span><br><span class="line">            <span class="punctuation">&#125;</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure>

<p>如果查询了不存在的索引，会返回错误信息，例如查询名称为book的索引后信息如下</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;error&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;root_cause&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">            <span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;index_not_found_exception&quot;</span><span class="punctuation">,</span></span><br><span class="line">                <span class="attr">&quot;reason&quot;</span><span class="punctuation">:</span> <span class="string">&quot;no such index [book]&quot;</span><span class="punctuation">,</span></span><br><span class="line">                <span class="attr">&quot;resource.type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;index_or_alias&quot;</span><span class="punctuation">,</span></span><br><span class="line">                <span class="attr">&quot;resource.id&quot;</span><span class="punctuation">:</span> <span class="string">&quot;book&quot;</span><span class="punctuation">,</span></span><br><span class="line">                <span class="attr">&quot;index_uuid&quot;</span><span class="punctuation">:</span> <span class="string">&quot;_na_&quot;</span><span class="punctuation">,</span></span><br><span class="line">                <span class="attr">&quot;index&quot;</span><span class="punctuation">:</span> <span class="string">&quot;book&quot;</span></span><br><span class="line">            <span class="punctuation">&#125;</span></span><br><span class="line">        <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;index_not_found_exception&quot;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;reason&quot;</span><span class="punctuation">:</span> <span class="string">&quot;no such index [book]&quot;</span><span class="punctuation">,</span>		# 没有book索引</span><br><span class="line">        <span class="attr">&quot;resource.type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;index_or_alias&quot;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;resource.id&quot;</span><span class="punctuation">:</span> <span class="string">&quot;book&quot;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;index_uuid&quot;</span><span class="punctuation">:</span> <span class="string">&quot;_na_&quot;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;index&quot;</span><span class="punctuation">:</span> <span class="string">&quot;book&quot;</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;status&quot;</span><span class="punctuation">:</span> <span class="number">404</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>删除索引</p>
<figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">DELETE请求	http://localhost:<span class="number">9200</span>/books</span><br></pre></td></tr></table></figure>

<p>删除所有后，给出删除结果</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;acknowledged&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure>

<p>如果重复删除，会给出错误信息，同样在reason属性中描述具体的错误原因</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;error&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;root_cause&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">            <span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;index_not_found_exception&quot;</span><span class="punctuation">,</span></span><br><span class="line">                <span class="attr">&quot;reason&quot;</span><span class="punctuation">:</span> <span class="string">&quot;no such index [books]&quot;</span><span class="punctuation">,</span></span><br><span class="line">                <span class="attr">&quot;resource.type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;index_or_alias&quot;</span><span class="punctuation">,</span></span><br><span class="line">                <span class="attr">&quot;resource.id&quot;</span><span class="punctuation">:</span> <span class="string">&quot;book&quot;</span><span class="punctuation">,</span></span><br><span class="line">                <span class="attr">&quot;index_uuid&quot;</span><span class="punctuation">:</span> <span class="string">&quot;_na_&quot;</span><span class="punctuation">,</span></span><br><span class="line">                <span class="attr">&quot;index&quot;</span><span class="punctuation">:</span> <span class="string">&quot;book&quot;</span></span><br><span class="line">            <span class="punctuation">&#125;</span></span><br><span class="line">        <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;index_not_found_exception&quot;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;reason&quot;</span><span class="punctuation">:</span> <span class="string">&quot;no such index [books]&quot;</span><span class="punctuation">,</span>		# 没有books索引</span><br><span class="line">        <span class="attr">&quot;resource.type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;index_or_alias&quot;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;resource.id&quot;</span><span class="punctuation">:</span> <span class="string">&quot;book&quot;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;index_uuid&quot;</span><span class="punctuation">:</span> <span class="string">&quot;_na_&quot;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;index&quot;</span><span class="punctuation">:</span> <span class="string">&quot;book&quot;</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;status&quot;</span><span class="punctuation">:</span> <span class="number">404</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>创建索引并指定分词器 </p>
<p>前面创建的索引是未指定分词器的，可以在创建索引时添加请求参数，设置分词器。目前国内较为流行的分词器是IK分词器，使用前先在下对应的分词器，然后使用。IK分词器下载地址：<a target="_blank" rel="noopener" href="https://github.com/medcl/elasticsearch-analysis-ik/releases">https://github.com/medcl/elasticsearch-analysis-ik/releases</a></p>
<p>分词器下载后解压到ES安装目录的plugins目录中即可，安装分词器后需要重新启动ES服务器。使用IK分词器创建索引格式：</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">PUT请求		http<span class="punctuation">:</span><span class="comment">//localhost:9200/books</span></span><br></pre></td></tr></table></figure>

<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;mappings&quot;</span><span class="punctuation">:</span><span class="punctuation">&#123;</span>							#定义mappings属性，替换创建索引时对应的mappings属性		</span><br><span class="line">        <span class="attr">&quot;properties&quot;</span><span class="punctuation">:</span><span class="punctuation">&#123;</span>						#定义索引中包含的属性设置</span><br><span class="line">            <span class="attr">&quot;id&quot;</span><span class="punctuation">:</span><span class="punctuation">&#123;</span>							#设置索引中包含id属性</span><br><span class="line">                <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span><span class="string">&quot;keyword&quot;</span>			#当前属性可以被直接搜索</span><br><span class="line">            <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span><span class="punctuation">&#123;</span>						#设置索引中包含name属性</span><br><span class="line">                <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span><span class="string">&quot;text&quot;</span><span class="punctuation">,</span>              #当前属性是文本信息，参与分词  </span><br><span class="line">                <span class="attr">&quot;analyzer&quot;</span><span class="punctuation">:</span><span class="string">&quot;ik_max_word&quot;</span><span class="punctuation">,</span>   #使用IK分词器进行分词             </span><br><span class="line">                <span class="attr">&quot;copy_to&quot;</span><span class="punctuation">:</span><span class="string">&quot;all&quot;</span>				#分词结果拷贝到all属性中</span><br><span class="line">            <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span><span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span><span class="string">&quot;keyword&quot;</span></span><br><span class="line">            <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;description&quot;</span><span class="punctuation">:</span><span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span><span class="string">&quot;text&quot;</span><span class="punctuation">,</span>	                </span><br><span class="line">                <span class="attr">&quot;analyzer&quot;</span><span class="punctuation">:</span><span class="string">&quot;ik_max_word&quot;</span><span class="punctuation">,</span>                </span><br><span class="line">                <span class="attr">&quot;copy_to&quot;</span><span class="punctuation">:</span><span class="string">&quot;all&quot;</span></span><br><span class="line">            <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;all&quot;</span><span class="punctuation">:</span><span class="punctuation">&#123;</span>							#定义属性，用来描述多个字段的分词结果集合，当前属性可以参与查询</span><br><span class="line">                <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span><span class="string">&quot;text&quot;</span><span class="punctuation">,</span>	                </span><br><span class="line">                <span class="attr">&quot;analyzer&quot;</span><span class="punctuation">:</span><span class="string">&quot;ik_max_word&quot;</span></span><br><span class="line">            <span class="punctuation">&#125;</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure>

<p>创建完毕后返回结果和不使用分词器创建索引的结果是一样的，此时可以通过查看索引信息观察到添加的请求参数mappings已经进入到了索引属性中 </p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;books&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;aliases&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span><span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;mappings&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">          <span class="attr">&quot;properties&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">              <span class="attr">&quot;all&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                  <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;text&quot;</span><span class="punctuation">,</span></span><br><span class="line">                  <span class="attr">&quot;analyzer&quot;</span><span class="punctuation">:</span> <span class="string">&quot;ik_max_word&quot;</span></span><br><span class="line">              <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">              <span class="attr">&quot;description&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                  <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;text&quot;</span><span class="punctuation">,</span></span><br><span class="line">                  <span class="attr">&quot;copy_to&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">                      <span class="string">&quot;all&quot;</span></span><br><span class="line">                  <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">                  <span class="attr">&quot;analyzer&quot;</span><span class="punctuation">:</span> <span class="string">&quot;ik_max_word&quot;</span></span><br><span class="line">              <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">              <span class="attr">&quot;id&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                  <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;keyword&quot;</span></span><br><span class="line">              <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">              <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                  <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;text&quot;</span><span class="punctuation">,</span></span><br><span class="line">                  <span class="attr">&quot;copy_to&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">                      <span class="string">&quot;all&quot;</span></span><br><span class="line">                  <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">                  <span class="attr">&quot;analyzer&quot;</span><span class="punctuation">:</span> <span class="string">&quot;ik_max_word&quot;</span></span><br><span class="line">              <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">              <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                  <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;keyword&quot;</span></span><br><span class="line">              <span class="punctuation">&#125;</span></span><br><span class="line">          <span class="punctuation">&#125;</span></span><br><span class="line">      <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;settings&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">          <span class="attr">&quot;index&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">              <span class="attr">&quot;routing&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                  <span class="attr">&quot;allocation&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                      <span class="attr">&quot;include&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                          <span class="attr">&quot;_tier_preference&quot;</span><span class="punctuation">:</span> <span class="string">&quot;data_content&quot;</span></span><br><span class="line">                      <span class="punctuation">&#125;</span></span><br><span class="line">                  <span class="punctuation">&#125;</span></span><br><span class="line">              <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">              <span class="attr">&quot;number_of_shards&quot;</span><span class="punctuation">:</span> <span class="string">&quot;1&quot;</span><span class="punctuation">,</span></span><br><span class="line">              <span class="attr">&quot;provided_name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;books&quot;</span><span class="punctuation">,</span></span><br><span class="line">              <span class="attr">&quot;creation_date&quot;</span><span class="punctuation">:</span> <span class="string">&quot;1693537543143&quot;</span><span class="punctuation">,</span></span><br><span class="line">              <span class="attr">&quot;number_of_replicas&quot;</span><span class="punctuation">:</span> <span class="string">&quot;1&quot;</span><span class="punctuation">,</span></span><br><span class="line">              <span class="attr">&quot;uuid&quot;</span><span class="punctuation">:</span> <span class="string">&quot;gRAAUTkDQj-_r4WxaDRs3Q&quot;</span><span class="punctuation">,</span></span><br><span class="line">              <span class="attr">&quot;version&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                  <span class="attr">&quot;created&quot;</span><span class="punctuation">:</span> <span class="string">&quot;7160299&quot;</span></span><br><span class="line">              <span class="punctuation">&#125;</span></span><br><span class="line">          <span class="punctuation">&#125;</span></span><br><span class="line">      <span class="punctuation">&#125;</span></span><br><span class="line">  <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure></li>
</ul>
<p>目前我们已经有了索引了，但是索引中还没有数据，所以要先添加数据，ES中称数据为文档，下面进行文档操作。 </p>
<ul>
<li>添加文档，有三种方式<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">POST请求	http<span class="punctuation">:</span><span class="comment">//localhost:9200/books/_doc		#使用系统生成id</span></span><br></pre></td></tr></table></figure></li>
</ul>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">POST请求	http<span class="punctuation">:</span><span class="comment">//localhost:9200/books/_create/1	#使用指定id</span></span><br></pre></td></tr></table></figure>

<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">POST请求	http<span class="punctuation">:</span><span class="comment">//localhost:9200/books/_doc/1		#使用指定id，不存在创建，</span></span><br></pre></td></tr></table></figure>
<p>文档通过请求参数传递，数据格式json</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span><span class="string">&quot;springboot&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span><span class="string">&quot;springboot&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;description&quot;</span><span class="punctuation">:</span><span class="string">&quot;springboot&quot;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure>
<ul>
<li>查询文档</li>
</ul>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">GET请求	http<span class="punctuation">:</span><span class="comment">//localhost:9200/books/_doc/1		 #查询单个文档 		</span></span><br><span class="line">GET请求	http<span class="punctuation">:</span><span class="comment">//localhost:9200/books/_search		 #查询全部文档</span></span><br></pre></td></tr></table></figure>
<ul>
<li>条件查询</li>
</ul>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">GET请求	http<span class="punctuation">:</span><span class="comment">//localhost:9200/books/_search?q=name:springboot2    # q=查询属性名:查询属性值</span></span><br></pre></td></tr></table></figure>

<ul>
<li>删除文档</li>
</ul>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">DELETE请求	http<span class="punctuation">:</span><span class="comment">//localhost:9200/books/_doc/1</span></span><br></pre></td></tr></table></figure>


<ul>
<li>修改文档（全量更新）</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">PUT请求	http://localhost:9200/books/_doc/1</span><br></pre></td></tr></table></figure>

<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">文档通过请求参数传递，数据格式json</span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span><span class="string">&quot;springboot&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span><span class="string">&quot;springboot&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;description&quot;</span><span class="punctuation">:</span><span class="string">&quot;springboot&quot;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure>

<ul>
<li>修改文档（部分更新）</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">POST请求	http://localhost:9200/books/_update/1</span><br></pre></td></tr></table></figure>

<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">文档通过请求参数传递，数据格式json</span><br><span class="line"><span class="punctuation">&#123;</span>			</span><br><span class="line">    <span class="attr">&quot;doc&quot;</span><span class="punctuation">:</span><span class="punctuation">&#123;</span>						#部分更新并不是对原始文档进行更新，而是对原始文档对象中的doc属性中的指定属性更新</span><br><span class="line">        <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span><span class="string">&quot;springboot&quot;</span>		#仅更新提供的属性值，未提供的属性值不参与更新操作</span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure>

<h5 id="整合-2"><a href="#整合-2" class="headerlink" title="整合"></a>整合</h5><p>①导入依赖</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br></pre></td><td class="code"><pre><span class="line">    <span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.mysql<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mysql-connector-j<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">scope</span>&gt;</span>runtime<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-test<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">scope</span>&gt;</span>test<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.baomidou<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mybatis-plus-boot-starter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">version</span>&gt;</span>3.4.1<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.alibaba<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>druid<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.2.16<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.projectlombok<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>lombok<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-data-elasticsearch<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.alibaba<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>fastjson<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.0.32<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!--        &lt;dependency&gt;--&gt;</span></span><br><span class="line"><span class="comment">&lt;!--            &lt;groupId&gt;org.elasticsearch.client&lt;/groupId&gt;--&gt;</span></span><br><span class="line"><span class="comment">&lt;!--            &lt;artifactId&gt;elasticsearch-rest-high-level-client&lt;/artifactId&gt;--&gt;</span></span><br><span class="line"><span class="comment">&lt;!--        &lt;/dependency&gt;--&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>②配置</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">datasource:</span></span><br><span class="line">    <span class="attr">type:</span> <span class="string">com.alibaba.druid.pool.DruidDataSource</span></span><br><span class="line">    <span class="attr">driver-class-name:</span> <span class="string">com.mysql.cj.jdbc.Driver</span></span><br><span class="line">    <span class="attr">url:</span> <span class="string">jdbc:mysql://localhost:3306/db1</span></span><br><span class="line">    <span class="attr">username:</span> <span class="string">root</span></span><br><span class="line">    <span class="attr">password:</span> <span class="string">&quot;031006&quot;</span></span><br><span class="line">  <span class="attr">elasticsearch:</span></span><br><span class="line">    <span class="attr">uris:</span> <span class="string">http://localhost:9200</span></span><br><span class="line"></span><br><span class="line"><span class="attr">mybatis-plus:</span></span><br><span class="line">  <span class="attr">global-config:</span></span><br><span class="line">    <span class="attr">db-config:</span></span><br><span class="line">      <span class="attr">table-prefix:</span> <span class="string">tbl_</span></span><br><span class="line">      <span class="attr">id-type:</span> <span class="string">auto</span></span><br><span class="line">  <span class="attr">configuration:</span></span><br><span class="line">    <span class="attr">log-impl:</span> <span class="string">org.apache.ibatis.logging.stdout.StdOutImpl</span></span><br></pre></td></tr></table></figure>

<p>③测试</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.example;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.alibaba.fastjson.JSON;</span><br><span class="line"><span class="keyword">import</span> com.alibaba.fastjson.JSONObject;</span><br><span class="line"><span class="keyword">import</span> com.example.dao.BookDao;</span><br><span class="line"><span class="keyword">import</span> com.example.domain.Book;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.action.bulk.BulkRequest;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.action.get.GetRequest;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.action.get.GetResponse;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.action.index.IndexRequest;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.action.search.SearchRequest;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.action.search.SearchResponse;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.client.*;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.index.query.QueryBuilder;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.index.query.QueryBuilders;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.search.SearchHit;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.search.SearchHits;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.search.builder.SearchSourceBuilder;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.xcontent.XContentType;</span><br><span class="line"><span class="keyword">import</span> org.junit.jupiter.api.Test;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.boot.test.context.SpringBootTest;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.client.indices.CreateIndexRequest;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.io.IOException;</span><br><span class="line"><span class="keyword">import</span> java.util.List;</span><br><span class="line"></span><br><span class="line"><span class="meta">@SpringBootTest</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Springboot07EsApplicationTests</span> &#123;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> BookDao bookDao;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> RestHighLevelClient client;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 添加索引</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">testCreateIndex</span><span class="params">()</span> <span class="keyword">throws</span> IOException &#123;</span><br><span class="line"></span><br><span class="line">        <span class="type">CreateIndexRequest</span> <span class="variable">request</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">CreateIndexRequest</span>(<span class="string">&quot;books&quot;</span>);</span><br><span class="line">        client.indices().create(request, RequestOptions.DEFAULT);</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 添加索引</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">testCreateIndexByIK</span><span class="params">()</span> <span class="keyword">throws</span> IOException &#123;</span><br><span class="line"></span><br><span class="line">        <span class="type">CreateIndexRequest</span> <span class="variable">request</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">CreateIndexRequest</span>(<span class="string">&quot;books&quot;</span>);</span><br><span class="line">        <span class="type">String</span> <span class="variable">json</span> <span class="operator">=</span> <span class="string">&quot;&#123;\n&quot;</span> +</span><br><span class="line">                <span class="string">&quot;    \&quot;mappings\&quot;:&#123;\n&quot;</span> +</span><br><span class="line">                <span class="string">&quot;        \&quot;properties\&quot;:&#123;\n&quot;</span> +</span><br><span class="line">                <span class="string">&quot;            \&quot;id\&quot;:&#123;\n&quot;</span> +</span><br><span class="line">                <span class="string">&quot;                \&quot;type\&quot;:\&quot;keyword\&quot;\n&quot;</span> +</span><br><span class="line">                <span class="string">&quot;            &#125;,\n&quot;</span> +</span><br><span class="line">                <span class="string">&quot;            \&quot;name\&quot;:&#123;\n&quot;</span> +</span><br><span class="line">                <span class="string">&quot;                \&quot;type\&quot;:\&quot;text\&quot;,\n&quot;</span> +</span><br><span class="line">                <span class="string">&quot;                \&quot;analyzer\&quot;:\&quot;ik_max_word\&quot;,\n&quot;</span> +</span><br><span class="line">                <span class="string">&quot;                \&quot;copy_to\&quot;:\&quot;all\&quot;\n&quot;</span> +</span><br><span class="line">                <span class="string">&quot;            &#125;,\n&quot;</span> +</span><br><span class="line">                <span class="string">&quot;            \&quot;type\&quot;:&#123;\n&quot;</span> +</span><br><span class="line">                <span class="string">&quot;                \&quot;type\&quot;:\&quot;keyword\&quot;\n&quot;</span> +</span><br><span class="line">                <span class="string">&quot;            &#125;,\n&quot;</span> +</span><br><span class="line">                <span class="string">&quot;            \&quot;description\&quot;:&#123;\n&quot;</span> +</span><br><span class="line">                <span class="string">&quot;                \&quot;type\&quot;:\&quot;text\&quot;,\n&quot;</span> +</span><br><span class="line">                <span class="string">&quot;                \&quot;analyzer\&quot;:\&quot;ik_max_word\&quot;,\n&quot;</span> +</span><br><span class="line">                <span class="string">&quot;                \&quot;copy_to\&quot;:\&quot;all\&quot;\n&quot;</span> +</span><br><span class="line">                <span class="string">&quot;            &#125;,\n&quot;</span> +</span><br><span class="line">                <span class="string">&quot;            \&quot;all\&quot;:&#123;\n&quot;</span> +</span><br><span class="line">                <span class="string">&quot;                \&quot;type\&quot;:\&quot;text\&quot;,\n&quot;</span> +</span><br><span class="line">                <span class="string">&quot;                \&quot;analyzer\&quot;:\&quot;ik_max_word\&quot;\n&quot;</span> +</span><br><span class="line">                <span class="string">&quot;            &#125;\n&quot;</span> +</span><br><span class="line">                <span class="string">&quot;        &#125;\n&quot;</span> +</span><br><span class="line">                <span class="string">&quot;    &#125;\n&quot;</span> +</span><br><span class="line">                <span class="string">&quot;&#125;&quot;</span>;</span><br><span class="line">        <span class="comment">//设置请求中的参数</span></span><br><span class="line">        request.source(json, XContentType.JSON);</span><br><span class="line">        client.indices().create(request, RequestOptions.DEFAULT);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 添加文档</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">testCreateDoc</span><span class="params">()</span> <span class="keyword">throws</span> IOException &#123;</span><br><span class="line">        <span class="type">Book</span> <span class="variable">book</span> <span class="operator">=</span> bookDao.selectById(<span class="number">1</span>);</span><br><span class="line">        <span class="type">IndexRequest</span> <span class="variable">request</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">IndexRequest</span>(<span class="string">&quot;books&quot;</span>).id(book.getId().toString());</span><br><span class="line">        <span class="comment">//设置请求中的参数</span></span><br><span class="line">        <span class="type">String</span> <span class="variable">json</span> <span class="operator">=</span> JSON.toJSONString(book);</span><br><span class="line">        request.source(json, XContentType.JSON);</span><br><span class="line">        client.index(request, RequestOptions.DEFAULT);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 批量添加文档</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">testCreateDocAll</span><span class="params">()</span> <span class="keyword">throws</span> IOException &#123;</span><br><span class="line">        List&lt;Book&gt; bookList = bookDao.selectList(<span class="literal">null</span>);</span><br><span class="line">        <span class="type">BulkRequest</span> <span class="variable">bulk</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">BulkRequest</span>();</span><br><span class="line">        <span class="keyword">for</span> (Book book : bookList) &#123;</span><br><span class="line">            <span class="type">IndexRequest</span> <span class="variable">request</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">IndexRequest</span>(<span class="string">&quot;books&quot;</span>).id(book.getId().toString());</span><br><span class="line">            <span class="type">String</span> <span class="variable">json</span> <span class="operator">=</span> JSON.toJSONString(book);</span><br><span class="line">            request.source(json, XContentType.JSON);</span><br><span class="line">            bulk.add(request);</span><br><span class="line">            client.bulk(bulk, RequestOptions.DEFAULT);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 根据id查询</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">testGetById</span><span class="params">()</span> <span class="keyword">throws</span> IOException &#123;</span><br><span class="line">        <span class="type">GetRequest</span> <span class="variable">request</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">GetRequest</span>(<span class="string">&quot;books&quot;</span>,<span class="string">&quot;1&quot;</span>);</span><br><span class="line">        <span class="type">GetResponse</span> <span class="variable">response</span> <span class="operator">=</span> client.get(request, RequestOptions.DEFAULT);</span><br><span class="line">        <span class="type">String</span> <span class="variable">source</span> <span class="operator">=</span> response.getSourceAsString();</span><br><span class="line">        System.out.println(source);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 根据条件查询</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">testSearch</span><span class="params">()</span> <span class="keyword">throws</span> IOException &#123;</span><br><span class="line">        <span class="type">SearchRequest</span> <span class="variable">request</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">SearchRequest</span>(<span class="string">&quot;books&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="type">SearchSourceBuilder</span> <span class="variable">build</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">SearchSourceBuilder</span>();</span><br><span class="line">        build.query(QueryBuilders.matchPhraseQuery(<span class="string">&quot;all&quot;</span>,<span class="string">&quot;Spring&quot;</span>));</span><br><span class="line">        request.source(build);</span><br><span class="line"></span><br><span class="line">        <span class="type">SearchResponse</span> <span class="variable">response</span> <span class="operator">=</span> client.search(request, RequestOptions.DEFAULT);</span><br><span class="line">        <span class="type">SearchHits</span> <span class="variable">hits</span> <span class="operator">=</span> response.getHits();</span><br><span class="line">        <span class="keyword">for</span> (SearchHit hit : hits) &#123;</span><br><span class="line">            <span class="type">String</span> <span class="variable">source</span> <span class="operator">=</span> hit.getSourceAsString();</span><br><span class="line">            <span class="comment">// System.out.println(source);</span></span><br><span class="line">            <span class="type">Book</span> <span class="variable">book</span> <span class="operator">=</span> JSON.parseObject(source, Book.class);</span><br><span class="line">            System.out.println(book);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="整合第三方技术"><a href="#整合第三方技术" class="headerlink" title="整合第三方技术"></a>整合第三方技术</h2><h3 id="缓存"><a href="#缓存" class="headerlink" title="缓存"></a>缓存</h3><p>缓存是一种介于数据永久存储介质与数据应用之间的数据临时存储介质<br>使用缓存可以有效的减少低速数据读取过程的次数（例如磁盘IO），提高系统性能</p>
<p>缓存不仅可以用于提高永久性存储介质的数据读取效率，还可以提供临时的数据存储空间</p>
<h4 id="SpringBoot内置缓存解决方案"><a href="#SpringBoot内置缓存解决方案" class="headerlink" title="SpringBoot内置缓存解决方案"></a>SpringBoot内置缓存解决方案</h4><p>springboot技术提供有内置的缓存解决方案，可以帮助开发者快速开启缓存技术，并使用缓存技术进行数据的快速操作，例如读取缓存数据和写入数据到缓存。</p>
<p><strong>步骤①</strong>：导入springboot提供的缓存技术对应的starter</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--cache--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-cache<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p><strong>步骤②</strong>：启用缓存，在引导类上方标注注解@EnableCaching配置springboot程序中可以使用缓存 </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.example;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> org.springframework.boot.SpringApplication;</span><br><span class="line"><span class="keyword">import</span> org.springframework.boot.autoconfigure.SpringBootApplication;</span><br><span class="line"><span class="keyword">import</span> org.springframework.cache.annotation.EnableCaching;</span><br><span class="line"></span><br><span class="line"><span class="meta">@SpringBootApplication</span></span><br><span class="line"><span class="comment">// 开启缓存功能</span></span><br><span class="line"><span class="meta">@EnableCaching</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Springboot08EsApplication</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        SpringApplication.run(Springboot08EsApplication.class, args);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>步骤③</strong>：设置操作的数据是否使用缓存</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.example.service.impl;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.example.dao.BookDao;</span><br><span class="line"><span class="keyword">import</span> com.example.domain.Book;</span><br><span class="line"><span class="keyword">import</span> com.example.service.BookService;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.cache.annotation.Cacheable;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Service;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">BookServiceImpl</span> <span class="keyword">implements</span> <span class="title class_">BookService</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> BookDao bookDao;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="meta">@Cacheable(value = &quot;cacheSpace&quot;,key = &quot;#id&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> Book <span class="title function_">getById</span><span class="params">(Integer id)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> bookDao.selectById(id);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>在业务方法上面使用注解@Cacheable声明当前方法的返回值放入缓存中，其中要指定缓存的存储位置，以及缓存中保存当前方法返回值对应的名称。上例中value属性描述缓存的存储位置，可以理解为是一个存储空间名，key属性描述了缓存中保存数据的名称，使用#id读取形参中的id值作为缓存名称。</p>
<p>使用@Cacheable注解后，执行当前操作，如果发现对应名称在缓存中没有数据，就正常读取数据，然后放入缓存；如果对应名称在缓存中有数据，就终止当前业务方法执行，直接返回缓存中的数据。</p>
<h4 id="手机验证码案例"><a href="#手机验证码案例" class="headerlink" title="手机验证码案例"></a>手机验证码案例</h4><p>手机验证码案例需求如下： </p>
<ul>
<li>输入手机号获取验证码，组织文档以短信形式发送给用户（页面模拟）</li>
<li>输入手机号和验证码验证结果</li>
</ul>
<p>为了描述上述操作，我们制作两个表现层接口，一个用来模拟发送短信的过程，其实就是根据用户提供的手机号生成一个验证码，然后放入缓存，另一个用来模拟验证码校验的过程，其实就是使用传入的手机号和验证码进行匹配，并返回最终匹配结果。 </p>
<p><strong>步骤①</strong>：导入springboot提供的缓存技术对应的starter </p>
<p><strong>步骤②</strong>：启用缓存，在引导类上方标注注解@EnableCaching配置springboot程序中可以使用缓存 </p>
<p><strong>步骤③</strong>：定义验证码对应的实体类，封装手机号与验证码两个属性 </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.example.domain;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> lombok.Data;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SMSCode</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> String tele;</span><br><span class="line">    <span class="keyword">private</span> String code;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>步骤④</strong>：定义验证码功能的业务层接口与实现类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.example.service;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.example.domain.SMSCode;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">SMSCodeService</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">sendCodeToSMS</span><span class="params">(String tele)</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">checkCode</span><span class="params">(SMSCode smsCode)</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.example.service.impl;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.example.domain.SMSCode;</span><br><span class="line"><span class="keyword">import</span> com.example.service.SMSCodeService;</span><br><span class="line"><span class="keyword">import</span> com.example.utils.CodeUtils;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.cache.annotation.CachePut;</span><br><span class="line"><span class="keyword">import</span> org.springframework.cache.annotation.Cacheable;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Service;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SMSCodeServiceImpl</span> <span class="keyword">implements</span> <span class="title class_">SMSCodeService</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">public</span> CodeUtils codeUtils;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line"><span class="comment">//    @Cacheable(value = &quot;smsCode&quot;,key = &quot;#tele&quot;)</span></span><br><span class="line">    <span class="meta">@CachePut(value = &quot;smsCode&quot;,key = &quot;#tele&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">sendCodeToSMS</span><span class="params">(String tele)</span> &#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">code</span> <span class="operator">=</span> codeUtils.generator(tele);</span><br><span class="line">        <span class="keyword">return</span> code;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">checkCode</span><span class="params">(SMSCode smsCode)</span> &#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">code</span> <span class="operator">=</span> smsCode.getCode();</span><br><span class="line">        <span class="type">String</span> <span class="variable">cacheCode</span> <span class="operator">=</span> codeUtils.get(smsCode.getTele());</span><br><span class="line">        <span class="keyword">return</span> code.equals(cacheCode);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>获取验证码后，当验证码失效时必须重新获取验证码，因此在获取验证码的功能上不能使用@Cacheable注解，@Cacheable注解是缓存中没有值则放入值，缓存中有值则取值。 应该使用仅具有向缓存中保存数据的功能，使用@CachePut注解即可。 </p>
<p><strong>步骤⑤</strong>：定义验证码的生成策略与根据手机号读取验证码的功能 </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.example.utils;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Value;</span><br><span class="line"><span class="keyword">import</span> org.springframework.cache.annotation.Cacheable;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Component;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CodeUtils</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> String [] patch = &#123;<span class="string">&quot;000000&quot;</span>,<span class="string">&quot;00000&quot;</span>,<span class="string">&quot;0000&quot;</span>,<span class="string">&quot;000&quot;</span>,<span class="string">&quot;00&quot;</span>,<span class="string">&quot;0&quot;</span>,<span class="string">&quot;&quot;</span>&#125;;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">generator</span><span class="params">(String tele)</span>&#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">hash</span> <span class="operator">=</span> tele.hashCode();</span><br><span class="line">        <span class="type">int</span> <span class="variable">encryption</span> <span class="operator">=</span> <span class="number">20236666</span>;</span><br><span class="line">        <span class="type">long</span> <span class="variable">result</span> <span class="operator">=</span> hash ^ encryption;</span><br><span class="line">        <span class="type">long</span> <span class="variable">nowTime</span> <span class="operator">=</span> System.currentTimeMillis();</span><br><span class="line">        result = result ^ nowTime;</span><br><span class="line">        <span class="type">long</span> <span class="variable">code</span> <span class="operator">=</span> result % <span class="number">1000000</span>;</span><br><span class="line">        code = code &lt; <span class="number">0</span> ? -code : code;</span><br><span class="line">        <span class="type">String</span> <span class="variable">codeStr</span> <span class="operator">=</span> code + <span class="string">&quot;&quot;</span>;</span><br><span class="line">        <span class="type">int</span> <span class="variable">len</span> <span class="operator">=</span> codeStr.length();</span><br><span class="line">        <span class="keyword">return</span> patch[len] + codeStr;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Cacheable(value = &quot;smsCode&quot;,key = &quot;#tele&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">get</span><span class="params">(String tele)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        System.out.println(<span class="keyword">new</span> <span class="title class_">CodeUtils</span>().generator(<span class="string">&quot;15166605999&quot;</span>));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>步骤⑥</strong>：定义验证码功能的web层接口，一个方法用于提供手机号获取验证码，一个方法用于提供手机号和验证码进行校验 </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.example.contorller;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.example.domain.SMSCode;</span><br><span class="line"><span class="keyword">import</span> com.example.service.SMSCodeService;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.GetMapping;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.PostMapping;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.RequestMapping;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.RestController;</span><br><span class="line"></span><br><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="meta">@RequestMapping(&quot;/sms&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SMSCodeController</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> SMSCodeService smsCodeService;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@GetMapping</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">getCode</span><span class="params">(String tele)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> smsCodeService.sendCodeToSMS(tele);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@PostMapping</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">check</span><span class="params">(SMSCode smsCode)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> smsCodeService.checkCode(smsCode);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="SpringBoot整合Ehcache缓存"><a href="#SpringBoot整合Ehcache缓存" class="headerlink" title="SpringBoot整合Ehcache缓存"></a>SpringBoot整合Ehcache缓存</h4><p>Ehcache是一种缓存技术，使用springboot整合Ehcache其实就是变更一下缓存技术的实现方式。</p>
<p><strong>步骤①</strong>：导入Ehcache的坐标 </p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>net.sf.ehcache<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>ehcache<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p><strong>步骤②</strong>：配置缓存技术实现使用Ehcache </p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">spring:</span><br><span class="line">  cache:</span><br><span class="line">    type: ehcache</span><br><span class="line">    ehcache:</span><br><span class="line">      config: ehcache.xml</span><br></pre></td></tr></table></figure>

<p>由于ehcache的配置有独立的配置文件格式，因此还需要指定ehcache的配置文件，以便于读取相应配置</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span>?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">ehcache</span> <span class="attr">xmlns:xsi</span>=<span class="string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span></span><br><span class="line"><span class="tag">         <span class="attr">xsi:noNamespaceSchemaLocation</span>=<span class="string">&quot;http://ehcache.org/ehcache.xsd&quot;</span></span></span><br><span class="line"><span class="tag">         <span class="attr">updateCheck</span>=<span class="string">&quot;false&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">diskStore</span> <span class="attr">path</span>=<span class="string">&quot;D:\ehcache&quot;</span> /&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--默认缓存策略 --&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- external：是否永久存在，设置为true则不会被清除，此时与timeout冲突，通常设置为false--&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- diskPersistent：是否启用磁盘持久化--&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- maxElementsInMemory：最大缓存数量--&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- overflowToDisk：超过最大缓存数量是否持久化到磁盘--&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- timeToIdleSeconds：最大不活动间隔，设置过长缓存容易溢出，设置过短无效果，可用于记录时效性数据，例如验证码--&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- timeToLiveSeconds：最大存活时间--&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- memoryStoreEvictionPolicy：缓存清除策略--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">defaultCache</span></span></span><br><span class="line"><span class="tag">        <span class="attr">eternal</span>=<span class="string">&quot;false&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">diskPersistent</span>=<span class="string">&quot;false&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">maxElementsInMemory</span>=<span class="string">&quot;1000&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">overflowToDisk</span>=<span class="string">&quot;false&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">timeToIdleSeconds</span>=<span class="string">&quot;60&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">timeToLiveSeconds</span>=<span class="string">&quot;60&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">memoryStoreEvictionPolicy</span>=<span class="string">&quot;LRU&quot;</span> /&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">cache</span></span></span><br><span class="line"><span class="tag">        <span class="attr">name</span>=<span class="string">&quot;smsCode&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">eternal</span>=<span class="string">&quot;false&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">diskPersistent</span>=<span class="string">&quot;false&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">maxElementsInMemory</span>=<span class="string">&quot;1000&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">overflowToDisk</span>=<span class="string">&quot;false&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">timeToIdleSeconds</span>=<span class="string">&quot;10&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">timeToLiveSeconds</span>=<span class="string">&quot;10&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">memoryStoreEvictionPolicy</span>=<span class="string">&quot;LRU&quot;</span> /&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">ehcache</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>前面的案例中，设置了数据保存的位置是smsCode </p>
<p>这个设定需要保障ehcache中有一个缓存空间名称叫做smsCode的配置，前后要统一。在企业开发过程中，通过设置不同名称的cache来设定不同的缓存策略，应用于不同的缓存数据。 </p>
<h4 id="SpringBoot整合Redis缓存"><a href="#SpringBoot整合Redis缓存" class="headerlink" title="SpringBoot整合Redis缓存"></a>SpringBoot整合Redis缓存</h4><p><strong>步骤①</strong>：导入redis的坐标 </p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-data-redis<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p><strong>步骤②</strong>：配置缓存技术实现使用redis </p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">cache:</span></span><br><span class="line">    <span class="attr">type:</span> <span class="string">redis</span></span><br><span class="line">  <span class="attr">redis:</span></span><br><span class="line">    <span class="attr">host:</span> <span class="string">localhost</span></span><br><span class="line">    <span class="attr">port:</span> <span class="number">6379</span></span><br></pre></td></tr></table></figure>

<p>如果需要对redis作为缓存进行配置，注意不是对原始的redis进行配置，而是配置redis作为缓存使用相关的配置，隶属于spring.cache.redis节点下 </p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">cache:</span></span><br><span class="line">    <span class="attr">type:</span> <span class="string">redis</span></span><br><span class="line">    <span class="attr">redis:</span></span><br><span class="line">      <span class="attr">use-key-prefix:</span> <span class="literal">true</span></span><br><span class="line">      <span class="attr">cache-null-values:</span> <span class="literal">false</span></span><br><span class="line">      <span class="attr">key-prefix:</span> <span class="string">s</span></span><br><span class="line">      <span class="attr">time-to-live:</span> <span class="string">20s</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">redis:</span></span><br><span class="line">    <span class="attr">host:</span> <span class="string">localhost</span></span><br><span class="line">    <span class="attr">port:</span> <span class="number">6379</span></span><br></pre></td></tr></table></figure>

<h4 id="SpringBoot整合Memcached缓存"><a href="#SpringBoot整合Memcached缓存" class="headerlink" title="SpringBoot整合Memcached缓存"></a>SpringBoot整合Memcached缓存</h4><p>安装服务的命令如下：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">memcached.exe -d install</span><br></pre></td></tr></table></figure>

<p>服务安装完毕后可以使用命令启动和停止服务:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">memcached.exe -d start</span><br><span class="line">memcached.exe -d stop</span><br></pre></td></tr></table></figure>

<p>由于memcached未被springboot收录为缓存解决方案，因此使用memcached需要通过手工硬编码的方式来使用。</p>
<p>memcached目前提供有三种客户端技术，分别是Memcached Client for Java、SpyMemcached和Xmemcached，其中性能指标各方面最好的客户端是Xmemcached。下面开始使用Xmemcached </p>
<p><strong>步骤①</strong>：导入xmemcached的坐标 </p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.googlecode.xmemcached<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>xmemcached<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.4.7<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p><strong>步骤②</strong>：配置memcached，制作memcached的配置类 </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.example.config;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> net.rubyeye.xmemcached.MemcachedClient;</span><br><span class="line"><span class="keyword">import</span> net.rubyeye.xmemcached.MemcachedClientBuilder;</span><br><span class="line"><span class="keyword">import</span> net.rubyeye.xmemcached.XMemcachedClientBuilder;</span><br><span class="line"><span class="keyword">import</span> org.springframework.context.annotation.Bean;</span><br><span class="line"><span class="keyword">import</span> org.springframework.context.annotation.Configuration;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.io.IOException;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">XmemcachedConfig</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="keyword">public</span> MemcachedClient <span class="title function_">getMemcachedClient</span><span class="params">()</span> <span class="keyword">throws</span> IOException &#123;</span><br><span class="line">        <span class="type">MemcachedClientBuilder</span> <span class="variable">memcachedClientBuilder</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">XMemcachedClientBuilder</span>(<span class="string">&quot;localhost:11211&quot;</span>);</span><br><span class="line">        <span class="type">MemcachedClient</span> <span class="variable">memcachedClient</span> <span class="operator">=</span> memcachedClientBuilder.build();</span><br><span class="line">        <span class="keyword">return</span> memcachedClient;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>memcached默认对外服务端口11211 。</p>
<p><strong>步骤③</strong>：使用xmemcached客户端操作缓存，注入MemcachedClient对象 </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.example.service.impl;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.example.domain.SMSCode;</span><br><span class="line"><span class="keyword">import</span> com.example.service.SMSCodeService;</span><br><span class="line"><span class="keyword">import</span> com.example.utils.CodeUtils;</span><br><span class="line"><span class="keyword">import</span> net.rubyeye.xmemcached.MemcachedClient;</span><br><span class="line"><span class="keyword">import</span> net.rubyeye.xmemcached.exception.MemcachedException;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.cache.annotation.CachePut;</span><br><span class="line"><span class="keyword">import</span> org.springframework.cache.annotation.Cacheable;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Service;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.TimeoutException;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SMSCodeServiceImpl</span> <span class="keyword">implements</span> <span class="title class_">SMSCodeService</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">public</span> CodeUtils codeUtils;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Spring Boot实用Xmemchched</span></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> MemcachedClient memcachedClient;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">sendCodeToSMS</span><span class="params">(String tele)</span> &#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">code</span> <span class="operator">=</span> codeUtils.generator(tele);</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            memcachedClient.set(tele,<span class="number">10</span>,code);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> code;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">checkCode</span><span class="params">(SMSCode smsCode)</span> &#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">code</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            code = memcachedClient.get(smsCode.getTele()).toString();</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> smsCode.getCode().equals(code);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p><strong>定义配置属性</strong> </p>
<p>以下过程采用属性配置方式进行</p>
<ul>
<li>定义配置类，加载必要的配置属性，读取配置文件中memcached节点信息</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.example.config;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> lombok.Data;</span><br><span class="line"><span class="keyword">import</span> org.springframework.boot.context.properties.ConfigurationProperties;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Component;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@ConfigurationProperties(prefix = &quot;mymemcached&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">XmemcachedProperties</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> String servers;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> poolSize;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">long</span> opTimeout;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<ul>
<li>定义memcached节点信息</li>
</ul>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">myMemcached:</span></span><br><span class="line">  <span class="attr">servers:</span> <span class="string">localhost:11211</span></span><br><span class="line">  <span class="attr">poolSize:</span> <span class="number">10</span></span><br><span class="line">  <span class="attr">opTimeout:</span> <span class="number">3000</span></span><br></pre></td></tr></table></figure>

<ul>
<li>在memcached配置类中加载信息</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.example.config;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> net.rubyeye.xmemcached.MemcachedClient;</span><br><span class="line"><span class="keyword">import</span> net.rubyeye.xmemcached.MemcachedClientBuilder;</span><br><span class="line"><span class="keyword">import</span> net.rubyeye.xmemcached.XMemcachedClientBuilder;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.context.annotation.Bean;</span><br><span class="line"><span class="keyword">import</span> org.springframework.context.annotation.Configuration;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.io.IOException;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">XmemcachedConfig</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    XmemcachedProperties xmemcachedProperties;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="keyword">public</span> MemcachedClient <span class="title function_">getMemcachedClient</span><span class="params">()</span> <span class="keyword">throws</span> IOException &#123;</span><br><span class="line">        <span class="type">MemcachedClientBuilder</span> <span class="variable">memcachedClientBuilder</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">XMemcachedClientBuilder</span>(xmemcachedProperties.getServers());</span><br><span class="line">        memcachedClientBuilder.setConnectionPoolSize(xmemcachedProperties.getPoolSize());</span><br><span class="line">        memcachedClientBuilder.setConnectTimeout(xmemcachedProperties.getOpTimeout());</span><br><span class="line">        <span class="type">MemcachedClient</span> <span class="variable">memcachedClient</span> <span class="operator">=</span> memcachedClientBuilder.build();</span><br><span class="line">        <span class="keyword">return</span> memcachedClient;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="SpringBoot整合jetcache缓存"><a href="#SpringBoot整合jetcache缓存" class="headerlink" title="SpringBoot整合jetcache缓存"></a>SpringBoot整合jetcache缓存</h4><p>jetcache严格意义上来说，并不是一个缓存解决方案，只能说他算是一个缓存框架，然后把别的缓存放到jetcache中管理，这样就可以支持AB缓存一起用了。 </p>
<p>目前jetcache支持的缓存方案本地缓存支持两种，远程缓存支持两种，分别如下：</p>
<ul>
<li>本地缓存（Local）<ul>
<li>LinkedHashMap</li>
<li>Caffeine</li>
</ul>
</li>
<li>远程缓存（Remote）<ul>
<li>Redis</li>
<li>Tair</li>
</ul>
</li>
</ul>
<h5 id="纯远程方案"><a href="#纯远程方案" class="headerlink" title="纯远程方案"></a>纯远程方案</h5><p><strong>步骤①</strong>：导入springboot整合jetcache对应的坐标starter，当前坐标默认使用的远程方案是redis </p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.alicp.jetcache<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>jetcache-starter-redis<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.6.2<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p><strong>步骤②</strong>：远程方案基本配置 </p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">jetcache:</span></span><br><span class="line">  <span class="attr">remote:</span></span><br><span class="line">    <span class="attr">default:</span></span><br><span class="line">      <span class="attr">type:</span> <span class="string">redis</span></span><br><span class="line">      <span class="attr">host:</span> <span class="string">localhost</span></span><br><span class="line">      <span class="attr">port:</span> <span class="number">6379</span></span><br><span class="line">      <span class="attr">poolConfig:</span></span><br><span class="line">        <span class="attr">maxTotal:</span> <span class="number">50</span></span><br></pre></td></tr></table></figure>

<p>其中poolConfig是必配项，否则会报错</p>
<p><strong>步骤③</strong>：启用缓存，在引导类上方标注注解@EnableCreateCacheAnnotation配置springboot程序中可以使用注解的形式创建缓存</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.example;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.alicp.jetcache.anno.config.EnableCreateCacheAnnotation;</span><br><span class="line"><span class="keyword">import</span> org.springframework.boot.SpringApplication;</span><br><span class="line"><span class="keyword">import</span> org.springframework.boot.autoconfigure.SpringBootApplication;</span><br><span class="line"></span><br><span class="line"><span class="meta">@SpringBootApplication</span></span><br><span class="line"><span class="comment">// jetcache启用缓存的主开关</span></span><br><span class="line"><span class="meta">@EnableCreateCacheAnnotation</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Springboot08EsApplication</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        SpringApplication.run(Springboot08EsApplication.class, args);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>步骤④</strong>：创建缓存对象Cache，并使用注解@CreateCache标记当前缓存的信息，然后使用Cache对象的API操作缓存，put写缓存，get读缓存。 </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.example.service.impl;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.alicp.jetcache.Cache;</span><br><span class="line"><span class="keyword">import</span> com.alicp.jetcache.anno.CreateCache;</span><br><span class="line"><span class="keyword">import</span> com.example.domain.SMSCode;</span><br><span class="line"><span class="keyword">import</span> com.example.service.SMSCodeService;</span><br><span class="line"><span class="keyword">import</span> com.example.utils.CodeUtils;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Service;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.TimeUnit;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SMSCodeServiceImpl</span> <span class="keyword">implements</span> <span class="title class_">SMSCodeService</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">public</span> CodeUtils codeUtils;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@CreateCache(name = &quot;jetCache&quot;,expire = 20,timeUnit = TimeUnit.SECONDS)</span></span><br><span class="line">    <span class="keyword">private</span> Cache&lt;String, String&gt; jetCache;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">sendCodeToSMS</span><span class="params">(String tele)</span> &#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">code</span> <span class="operator">=</span> codeUtils.generator(tele);</span><br><span class="line">        jetCache.put(tele,code);</span><br><span class="line">        <span class="keyword">return</span> code;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">checkCode</span><span class="params">(SMSCode smsCode)</span> &#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">code</span> <span class="operator">=</span> jetCache.get(smsCode.getTele());</span><br><span class="line">        <span class="keyword">return</span> smsCode.getCode().equals(code);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>上述方案中使用的是配置中定义的default缓存，其实这个default是个名字，可以随便写，也可以随便加。例如再添加一种缓存解决方案，参照如下配置进行： </p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">jetcache:</span></span><br><span class="line">  <span class="attr">remote:</span></span><br><span class="line">    <span class="attr">default:</span></span><br><span class="line">      <span class="attr">type:</span> <span class="string">redis</span></span><br><span class="line">      <span class="attr">host:</span> <span class="string">localhost</span></span><br><span class="line">      <span class="attr">port:</span> <span class="number">6379</span></span><br><span class="line">      <span class="attr">poolConfig:</span></span><br><span class="line">        <span class="attr">maxTotal:</span> <span class="number">50</span></span><br><span class="line">    <span class="attr">sms:</span></span><br><span class="line">      <span class="attr">type:</span> <span class="string">redis</span></span><br><span class="line">      <span class="attr">host:</span> <span class="string">localhost</span></span><br><span class="line">      <span class="attr">port:</span> <span class="number">6379</span></span><br><span class="line">      <span class="attr">poolConfig:</span></span><br><span class="line">        <span class="attr">maxTotal:</span> <span class="number">50</span></span><br></pre></td></tr></table></figure>

<p>如果想使用名称是sms的缓存，需要再创建缓存时指定参数area，声明使用对应缓存即可 </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.example.service.impl;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.alicp.jetcache.Cache;</span><br><span class="line"><span class="keyword">import</span> com.alicp.jetcache.anno.CreateCache;</span><br><span class="line"><span class="keyword">import</span> com.example.domain.SMSCode;</span><br><span class="line"><span class="keyword">import</span> com.example.service.SMSCodeService;</span><br><span class="line"><span class="keyword">import</span> com.example.utils.CodeUtils;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Service;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.TimeUnit;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SMSCodeServiceImpl</span> <span class="keyword">implements</span> <span class="title class_">SMSCodeService</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">public</span> CodeUtils codeUtils;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@CreateCache(area=&quot;sms&quot;,name = &quot;jetCache&quot;,expire = 20,timeUnit = TimeUnit.SECONDS)</span></span><br><span class="line">    <span class="keyword">private</span> Cache&lt;String, String&gt; jetCache;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">sendCodeToSMS</span><span class="params">(String tele)</span> &#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">code</span> <span class="operator">=</span> codeUtils.generator(tele);</span><br><span class="line">        jetCache.put(tele,code);</span><br><span class="line">        <span class="keyword">return</span> code;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">checkCode</span><span class="params">(SMSCode smsCode)</span> &#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">code</span> <span class="operator">=</span> jetCache.get(smsCode.getTele());</span><br><span class="line">        <span class="keyword">return</span> smsCode.getCode().equals(code);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h5 id="纯本地方案"><a href="#纯本地方案" class="headerlink" title="纯本地方案"></a>纯本地方案</h5><p><strong>步骤①</strong>：导入springboot整合jetcache对应的坐标starter </p>
<p><strong>步骤②</strong>：本地缓存基本配置 </p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">jetcache:</span></span><br><span class="line">  <span class="attr">local:</span></span><br><span class="line">    <span class="attr">default:</span></span><br><span class="line">      <span class="attr">type:</span> <span class="string">linkedhashmap</span></span><br><span class="line">      <span class="attr">keyConvertor:</span> <span class="string">fastjson</span></span><br><span class="line">    <span class="attr">sms:</span></span><br><span class="line">      <span class="attr">type:</span> <span class="string">linkedhashmap</span></span><br><span class="line">      <span class="attr">keyConvertor:</span> <span class="string">fastjson</span></span><br></pre></td></tr></table></figure>

<p>为了加速数据获取时key的匹配速度，jetcache要求指定key的类型转换器。简单说就是，如果你给了一个Object作为key的话，我先用key的类型转换器给转换成字符串，然后再保存。等到获取数据时，仍然是先使用给定的Object转换成字符串，然后根据字符串匹配。由于jetcache是阿里的技术，这里推荐key的类型转换器使用阿里的fastjson。 </p>
<p><strong>步骤③</strong>：启用缓存 </p>
<p><strong>步骤④</strong>：创建缓存对象Cache时，标注当前使用本地缓存 </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.example.service.impl;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.alicp.jetcache.Cache;</span><br><span class="line"><span class="keyword">import</span> com.alicp.jetcache.anno.CacheType;</span><br><span class="line"><span class="keyword">import</span> com.alicp.jetcache.anno.CreateCache;</span><br><span class="line"><span class="keyword">import</span> com.example.domain.SMSCode;</span><br><span class="line"><span class="keyword">import</span> com.example.service.SMSCodeService;</span><br><span class="line"><span class="keyword">import</span> com.example.utils.CodeUtils;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Service;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.TimeUnit;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SMSCodeServiceImpl</span> <span class="keyword">implements</span> <span class="title class_">SMSCodeService</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">public</span> CodeUtils codeUtils;</span><br><span class="line">    </span><br><span class="line">    <span class="meta">@CreateCache(area = &quot;sms&quot;, name = &quot;jetCache&quot;, expire = 20, timeUnit = TimeUnit.SECONDS,cacheType = CacheType.LOCAL)</span></span><br><span class="line">    <span class="keyword">private</span> Cache&lt;String, String&gt; jetCache;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">sendCodeToSMS</span><span class="params">(String tele)</span> &#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">code</span> <span class="operator">=</span> codeUtils.generator(tele);</span><br><span class="line">        jetCache.put(tele, code);</span><br><span class="line">        <span class="keyword">return</span> code;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">checkCode</span><span class="params">(SMSCode smsCode)</span> &#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">code</span> <span class="operator">=</span> jetCache.get(smsCode.getTele());</span><br><span class="line">        <span class="keyword">return</span> smsCode.getCode().equals(code);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>cacheType控制当前缓存使用本地缓存还是远程缓存，配置cacheType&#x3D;CacheType.LOCAL即使用本地缓存。 </p>
<h5 id="本地-远程方案"><a href="#本地-远程方案" class="headerlink" title="本地+远程方案"></a>本地+远程方案</h5><p>两种方案一起使用如何配置呢？其实就是将两种配置合并到一起就可以了。 </p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">jetcache:</span></span><br><span class="line">  <span class="attr">local:</span></span><br><span class="line">    <span class="attr">default:</span></span><br><span class="line">      <span class="attr">type:</span> <span class="string">linkedhashmap</span></span><br><span class="line">      <span class="attr">keyConvertor:</span> <span class="string">fastjson</span></span><br><span class="line">    <span class="attr">sms:</span></span><br><span class="line">      <span class="attr">type:</span> <span class="string">linkedhashmap</span></span><br><span class="line">      <span class="attr">keyConvertor:</span> <span class="string">fastjson</span></span><br><span class="line">  <span class="attr">remote:</span></span><br><span class="line">    <span class="attr">default:</span></span><br><span class="line">      <span class="attr">type:</span> <span class="string">redis</span></span><br><span class="line">      <span class="attr">host:</span> <span class="string">localhost</span></span><br><span class="line">      <span class="attr">port:</span> <span class="number">6379</span></span><br><span class="line">      <span class="attr">poolConfig:</span></span><br><span class="line">        <span class="attr">maxTotal:</span> <span class="number">50</span></span><br><span class="line">    <span class="attr">sms:</span></span><br><span class="line">      <span class="attr">type:</span> <span class="string">redis</span></span><br><span class="line">      <span class="attr">host:</span> <span class="string">localhost</span></span><br><span class="line">      <span class="attr">port:</span> <span class="number">6379</span></span><br><span class="line">      <span class="attr">poolConfig:</span></span><br><span class="line">        <span class="attr">maxTotal:</span> <span class="number">50</span></span><br></pre></td></tr></table></figure>

<p>在创建缓存的时候，配置cacheType为BOTH即则本地缓存与远程缓存同时使用。 </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.example.service.impl;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.alicp.jetcache.Cache;</span><br><span class="line"><span class="keyword">import</span> com.alicp.jetcache.anno.CacheType;</span><br><span class="line"><span class="keyword">import</span> com.alicp.jetcache.anno.CreateCache;</span><br><span class="line"><span class="keyword">import</span> com.example.domain.SMSCode;</span><br><span class="line"><span class="keyword">import</span> com.example.service.SMSCodeService;</span><br><span class="line"><span class="keyword">import</span> com.example.utils.CodeUtils;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Service;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.TimeUnit;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SMSCodeServiceImpl</span> <span class="keyword">implements</span> <span class="title class_">SMSCodeService</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">public</span> CodeUtils codeUtils;</span><br><span class="line">    </span><br><span class="line">    <span class="meta">@CreateCache(area = &quot;sms&quot;, name = &quot;jetCache&quot;, expire = 20, timeUnit = TimeUnit.SECONDS,cacheType = CacheType.BOTH)</span></span><br><span class="line">    <span class="keyword">private</span> Cache&lt;String, String&gt; jetCache;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">sendCodeToSMS</span><span class="params">(String tele)</span> &#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">code</span> <span class="operator">=</span> codeUtils.generator(tele);</span><br><span class="line">        jetCache.put(tele, code);</span><br><span class="line">        <span class="keyword">return</span> code;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">checkCode</span><span class="params">(SMSCode smsCode)</span> &#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">code</span> <span class="operator">=</span> jetCache.get(smsCode.getTele());</span><br><span class="line">        <span class="keyword">return</span> smsCode.getCode().equals(code);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>cacheType如果不进行配置，默认值是REMOTE，即仅使用远程缓存方案。 </p>
<h5 id="jetcache的一些配置"><a href="#jetcache的一些配置" class="headerlink" title="jetcache的一些配置"></a>jetcache的一些配置</h5><table>
<thead>
<tr>
<th>属性</th>
<th>默认值</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>jetcache.statIntervalMinutes</td>
<td>0</td>
<td>统计间隔，0表示不统计</td>
</tr>
<tr>
<td>jetcache.hiddenPackages</td>
<td>无</td>
<td>自动生成name时，隐藏指定的包名前缀</td>
</tr>
<tr>
<td>jetcache.[local|remote].${area}.type</td>
<td>无</td>
<td>缓存类型，本地支持linkedhashmap、caffeine，远程支持redis、tair</td>
</tr>
<tr>
<td>jetcache.[local|remote].${area}.keyConvertor</td>
<td>无</td>
<td>key转换器，当前仅支持fastjson</td>
</tr>
<tr>
<td>jetcache.[local|remote].${area}.valueEncoder</td>
<td>java</td>
<td>仅remote类型的缓存需要指定，可选java和kryo</td>
</tr>
<tr>
<td>jetcache.[local|remote].${area}.valueDecoder</td>
<td>java</td>
<td>仅remote类型的缓存需要指定，可选java和kryo</td>
</tr>
<tr>
<td>jetcache.[local|remote].${area}.limit</td>
<td>100</td>
<td>仅local类型的缓存需要指定，缓存实例最大元素数</td>
</tr>
<tr>
<td>jetcache.[local|remote].${area}.expireAfterWriteInMillis</td>
<td>无穷大</td>
<td>默认过期时间，毫秒单位</td>
</tr>
<tr>
<td>jetcache.local.${area}.expireAfterAccessInMillis</td>
<td>0</td>
<td>仅local类型的缓存有效，毫秒单位，最大不活动间隔</td>
</tr>
</tbody></table>
<h5 id="方法缓存"><a href="#方法缓存" class="headerlink" title="方法缓存"></a>方法缓存</h5><p><strong>步骤①</strong>：导入springboot整合jetcache对应的坐标starter </p>
<p><strong>步骤②</strong>：配置缓存 </p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">jetcache:</span></span><br><span class="line">  <span class="attr">local:</span></span><br><span class="line">    <span class="attr">default:</span></span><br><span class="line">      <span class="attr">type:</span> <span class="string">linkedhashmap</span></span><br><span class="line">      <span class="attr">keyConvertor:</span> <span class="string">fastjson</span></span><br><span class="line">    <span class="attr">sms:</span></span><br><span class="line">      <span class="attr">type:</span> <span class="string">linkedhashmap</span></span><br><span class="line">      <span class="attr">keyConvertor:</span> <span class="string">fastjson</span></span><br><span class="line">  <span class="attr">remote:</span></span><br><span class="line">    <span class="attr">default:</span></span><br><span class="line">      <span class="attr">keyConvertor:</span> <span class="string">fastjson</span></span><br><span class="line">      <span class="attr">valueEncode:</span> <span class="string">java</span></span><br><span class="line">      <span class="attr">valueDecode:</span> <span class="string">java</span></span><br><span class="line">      <span class="attr">type:</span> <span class="string">redis</span></span><br><span class="line">      <span class="attr">host:</span> <span class="string">localhost</span></span><br><span class="line">      <span class="attr">port:</span> <span class="number">6379</span></span><br><span class="line">      <span class="attr">poolConfig:</span></span><br><span class="line">        <span class="attr">maxTotal:</span> <span class="number">50</span></span><br><span class="line">    <span class="attr">sms:</span></span><br><span class="line">      <span class="attr">type:</span> <span class="string">redis</span></span><br><span class="line">      <span class="attr">host:</span> <span class="string">localhost</span></span><br><span class="line">      <span class="attr">port:</span> <span class="number">6379</span></span><br><span class="line">      <span class="attr">poolConfig:</span></span><br><span class="line">        <span class="attr">maxTotal:</span> <span class="string">50v</span></span><br></pre></td></tr></table></figure>

<p>由于redis缓存中不支持保存对象，因此需要对redis设置当Object类型数据进入到redis中时如何进行类型转换。需要配置keyConvertor表示key的类型转换方式，同时标注value的转换类型方式，值进入redis时是java类型，标注valueEncode为java，值从redis中读取时转换成java，标注valueDecode为java。 </p>
<p>为了实现Object类型的值进出redis，需要保障进出redis的Object类型的数据必须实现序列化接口。 </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Book</span> <span class="keyword">implements</span> <span class="title class_">Serializable</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> Integer id;</span><br><span class="line">    <span class="keyword">private</span> String type;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> String description;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>步骤③</strong>：启用缓存时开启方法缓存功能，并配置basePackages，说明在哪些包中开启方法缓存 </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@SpringBootApplication</span></span><br><span class="line"><span class="comment">// jetcache启用缓存的主开关</span></span><br><span class="line"><span class="meta">@EnableCreateCacheAnnotation</span></span><br><span class="line"><span class="comment">// 开启方法注解缓存</span></span><br><span class="line"><span class="meta">@EnableMethodCache(basePackages = &quot;com.example&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Springboot08EsApplication</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        SpringApplication.run(Springboot08EsApplication.class, args);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>步骤④</strong>：使用注解@Cached标注当前方法使用缓存 </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">BookServiceImpl</span> <span class="keyword">implements</span> <span class="title class_">BookService</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> BookDao bookDao;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">save</span><span class="params">(Book book)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line"><span class="comment">//    @Cacheable(value = &quot;cacheSpace&quot;,key = &quot;#id&quot;)</span></span><br><span class="line">    <span class="meta">@Cached(name = &quot;book_&quot;, key = &quot;#id&quot;, expire = 3600, cacheType = CacheType.REMOTE)</span></span><br><span class="line">    <span class="keyword">public</span> Book <span class="title function_">getById</span><span class="params">(Integer id)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> bookDao.selectById(id);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="meta">@CacheUpdate(name = &quot;book_&quot;, key = &quot;#book.id&quot;, value = &quot;#book&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">update</span><span class="params">(Book book)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> bookDao.updateById(book) &gt; <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="meta">@CacheInvalidate(name = &quot;book_&quot;,key = &quot;#id&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">delete</span><span class="params">(Integer id)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> bookDao.deleteById(id) &gt; <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="远程方案的数据同步"><a href="#远程方案的数据同步" class="headerlink" title="远程方案的数据同步"></a>远程方案的数据同步</h5><p>由于远程方案中redis保存的数据可以被多个客户端共享，这就存在了数据同步问题。jetcache提供了3个注解解决此问题，分别在更新、删除操作时同步缓存数据，和读取缓存时定时刷新数据 </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.example.service.impl;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.alicp.jetcache.anno.*;</span><br><span class="line"><span class="keyword">import</span> com.example.dao.BookDao;</span><br><span class="line"><span class="keyword">import</span> com.example.domain.Book;</span><br><span class="line"><span class="keyword">import</span> com.example.service.BookService;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.cache.annotation.Cacheable;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Service;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">BookServiceImpl</span> <span class="keyword">implements</span> <span class="title class_">BookService</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> BookDao bookDao;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">save</span><span class="params">(Book book)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line"><span class="comment">//    @Cacheable(value = &quot;cacheSpace&quot;,key = &quot;#id&quot;)</span></span><br><span class="line">    <span class="meta">@Cached(name = &quot;book_&quot;, key = &quot;#id&quot;, expire = 3600, cacheType = CacheType.REMOTE)</span></span><br><span class="line">    <span class="meta">@CacheRefresh(refresh = 10)</span>  <span class="comment">// 10s</span></span><br><span class="line">    <span class="keyword">public</span> Book <span class="title function_">getById</span><span class="params">(Integer id)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> bookDao.selectById(id);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="meta">@CacheUpdate(name = &quot;book_&quot;, key = &quot;#book.id&quot;, value = &quot;#book&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">update</span><span class="params">(Book book)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> bookDao.updateById(book) &gt; <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="meta">@CacheInvalidate(name = &quot;book_&quot;,key = &quot;#id&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">delete</span><span class="params">(Integer id)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> bookDao.deleteById(id) &gt; <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="数据报表"><a href="#数据报表" class="headerlink" title="数据报表"></a>数据报表</h5><p>jetcache还提供有简单的数据报表功能，帮助开发者快速查看缓存命中信息，只需要添加一个配置即可</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">jetcache:</span></span><br><span class="line">  <span class="attr">statIntervalMinutes:</span> <span class="number">1</span></span><br><span class="line">  <span class="attr">local:</span></span><br><span class="line">    <span class="attr">default:</span></span><br><span class="line">      <span class="attr">type:</span> <span class="string">linkedhashmap</span></span><br><span class="line">      <span class="attr">keyConvertor:</span> <span class="string">fastjson</span></span><br><span class="line">    <span class="attr">sms:</span></span><br><span class="line">      <span class="attr">type:</span> <span class="string">linkedhashmap</span></span><br><span class="line">      <span class="attr">keyConvertor:</span> <span class="string">fastjson</span></span><br><span class="line">  <span class="attr">remote:</span></span><br><span class="line">    <span class="attr">default:</span></span><br><span class="line">      <span class="attr">keyConvertor:</span> <span class="string">fastjson</span></span><br><span class="line">      <span class="attr">valueEncode:</span> <span class="string">java</span></span><br><span class="line">      <span class="attr">valueDecode:</span> <span class="string">java</span></span><br><span class="line">      <span class="attr">type:</span> <span class="string">redis</span></span><br><span class="line">      <span class="attr">host:</span> <span class="string">localhost</span></span><br><span class="line">      <span class="attr">port:</span> <span class="number">6379</span></span><br><span class="line">      <span class="attr">poolConfig:</span></span><br><span class="line">        <span class="attr">maxTotal:</span> <span class="number">50</span></span><br><span class="line">    <span class="attr">sms:</span></span><br><span class="line">      <span class="attr">type:</span> <span class="string">redis</span></span><br><span class="line">      <span class="attr">host:</span> <span class="string">localhost</span></span><br><span class="line">      <span class="attr">port:</span> <span class="number">6379</span></span><br><span class="line">      <span class="attr">poolConfig:</span></span><br><span class="line">        <span class="attr">maxTotal:</span> <span class="number">50</span></span><br></pre></td></tr></table></figure>

<p>设置后，每1分钟在控制台输出缓存数据命中信息 </p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">2023-09-03 12:10:00.030  INFO 60396 --- [DefaultExecutor] c.alicp.jetcache.support.StatInfoLogger  : jetcache stat from 2023-09-03 12:09:07,156 to 2023-09-03 12:10:00,015</span><br><span class="line">cache        |       qps|   rate|           get|           hit|          fail|        expire|avgLoadTime|maxLoadTime</span><br><span class="line">-------------+----------+-------+--------------+--------------+--------------+--------------+-----------+-----------</span><br><span class="line">default_book_|      0.54| 73.08%|            26|            19|             0|             0|       26.3|        415</span><br><span class="line">-------------+----------+-------+--------------+--------------+--------------+--------------+-----------+-----------</span><br></pre></td></tr></table></figure>

<h4 id="SpringBoot整合j2cache缓存"><a href="#SpringBoot整合j2cache缓存" class="headerlink" title="SpringBoot整合j2cache缓存"></a>SpringBoot整合j2cache缓存</h4><p>j2cache是一个缓存整合框架，可以提供缓存的整合方案，使各种缓存搭配使用，自身不提供缓存功能</p>
<p><strong>步骤①</strong>：导入j2cache、redis、ehcache坐标 </p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>net.oschina.j2cache<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>j2cache-core<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.8.4-release<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>net.oschina.j2cache<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>j2cache-spring-boot2-starter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.8.0-release<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>net.sf.ehcache<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>ehcache<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>j2cache的starter中默认包含了redis坐标，官方推荐使用redis作为二级缓存，因此此处无需导入redis坐标 </p>
<p><strong>步骤②</strong>：配置一级与二级缓存，并配置一二级缓存间数据传递方式，配置书写在名称为j2cache.properties的文件中。如果使用ehcache还需要单独添加ehcache的配置文件 </p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">j2cache:</span></span><br><span class="line">  <span class="attr">config-location:</span> <span class="string">j2cache.properties</span></span><br></pre></td></tr></table></figure>

<figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 1级级存</span></span><br><span class="line"><span class="attr">j2cache.L1.provider_class</span> = <span class="string">ehcache</span></span><br><span class="line"><span class="attr">ehcache.configXml</span> = <span class="string">ehcache.xml</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment"># 2级缓存</span></span><br><span class="line"><span class="attr">j2cache.L2.provider_class</span> = <span class="string">net.oschina.j2cache.cache.support.redis.SpringRedisProvider</span></span><br><span class="line"><span class="attr">j2cache.L2.config_section</span> = <span class="string">redis</span></span><br><span class="line"><span class="attr">redis.hosts</span> = <span class="string">localhost:6379</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment"># 1级级存中的数揶如何到达二级级存</span></span><br><span class="line"><span class="attr">j2cache.broadcast</span> =<span class="string">net.oschina.j2cache.cache.support.redis.SpringRedisPubSubPolicy</span></span><br></pre></td></tr></table></figure>

<blockquote>
<p>此处配置不能乱配置，需要参照官方给出的配置说明进行。例如1级供应商选择ehcache，供应商名称仅仅是一个ehcache，但是2级供应商选择redis时要写专用的Spring整合Redis的供应商类名SpringRedisProvider，而且这个名称并不是所有的redis包中能提供的，也不是spring包中提供的。因此配置j2cache必须参照官方文档配置，而且还要去找专用的整合包，导入对应坐标才可以使用。</p>
<p>一级与二级缓存最重要的一个配置就是两者之间的数据沟通方式，此类配置也不是随意配置的，并且不同的缓存解决方案提供的数据沟通方式差异化很大，需要查询官方文档进行设置。</p>
</blockquote>
<p><strong>步骤③</strong>：使用缓存 </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Autowired</span></span><br><span class="line"><span class="keyword">private</span> CacheChannel cacheChannel;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> String <span class="title function_">sendCodeToSMS</span><span class="params">(String tele)</span> &#123;</span><br><span class="line">    <span class="type">String</span> <span class="variable">code</span> <span class="operator">=</span> codeUtils.generator(tele);</span><br><span class="line">    cacheChannel.set(<span class="string">&quot;sms&quot;</span>,tele,code);</span><br><span class="line">    <span class="keyword">return</span> code;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">checkCode</span><span class="params">(SMSCode smsCode)</span> &#123;</span><br><span class="line">    <span class="type">String</span> <span class="variable">code</span> <span class="operator">=</span> cacheChannel.get(<span class="string">&quot;sms&quot;</span>,smsCode.getTele()).asString();</span><br><span class="line">    <span class="keyword">return</span> smsCode.getCode().equals(code);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>j2cache-core核心包中的j2cache.properties文件 :</p>
<figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#J2Cache configuration</span></span><br><span class="line"><span class="comment">#########################################</span></span><br><span class="line"><span class="comment"># Cache Broadcast Method</span></span><br><span class="line"><span class="comment"># values:</span></span><br><span class="line"><span class="comment"># jgroups -&gt; use jgroups&#x27;s multicast</span></span><br><span class="line"><span class="comment"># redis -&gt; use redis publish/subscribe mechanism (using jedis)</span></span><br><span class="line"><span class="comment"># lettuce -&gt; use redis publish/subscribe mechanism (using lettuce, Recommend)</span></span><br><span class="line"><span class="comment"># rabbitmq -&gt; use RabbitMQ publisher/consumer mechanism</span></span><br><span class="line"><span class="comment"># rocketmq -&gt; use RocketMQ publisher/consumer mechanism</span></span><br><span class="line"><span class="comment"># none -&gt; don&#x27;t notify the other nodes in cluster</span></span><br><span class="line"><span class="comment"># xx.xxxx.xxxx.Xxxxx your own cache broadcast policy classname that implement net.oschina.j2cache.cluster.ClusterPolicy</span></span><br><span class="line"><span class="comment">#########################################</span></span><br><span class="line"><span class="attr">j2cache.broadcast</span> = <span class="string">redis</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment"># jgroups properties</span></span><br><span class="line"><span class="attr">jgroups.channel.name</span> = <span class="string">j2cache</span></span><br><span class="line"><span class="attr">jgroups.configXml</span> = <span class="string">/network.xml</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment"># RabbitMQ properties</span></span><br><span class="line"><span class="attr">rabbitmq.exchange</span> = <span class="string">j2cache</span></span><br><span class="line"><span class="attr">rabbitmq.host</span> = <span class="string">localhost</span></span><br><span class="line"><span class="attr">rabbitmq.port</span> = <span class="string">5672</span></span><br><span class="line"><span class="attr">rabbitmq.username</span> = <span class="string">guest</span></span><br><span class="line"><span class="attr">rabbitmq.password</span> = <span class="string">guest</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment"># RocketMQ properties</span></span><br><span class="line"><span class="attr">rocketmq.name</span> = <span class="string">j2cache</span></span><br><span class="line"><span class="attr">rocketmq.topic</span> = <span class="string">j2cache</span></span><br><span class="line"><span class="comment"># use ; to split multi hosts</span></span><br><span class="line"><span class="attr">rocketmq.hosts</span> = <span class="string">127.0.0.1:9876</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">#########################################</span></span><br><span class="line"><span class="comment"># Level 1&amp;2 provider</span></span><br><span class="line"><span class="comment"># values:</span></span><br><span class="line"><span class="comment"># none -&gt; disable this level cache</span></span><br><span class="line"><span class="comment"># ehcache -&gt; use ehcache2 as level 1 cache</span></span><br><span class="line"><span class="comment"># ehcache3 -&gt; use ehcache3 as level 1 cache</span></span><br><span class="line"><span class="comment"># caffeine -&gt; use caffeine as level 1 cache(only in memory)</span></span><br><span class="line"><span class="comment"># redis -&gt; use redis as level 2 cache (using jedis)</span></span><br><span class="line"><span class="comment"># lettuce -&gt; use redis as level 2 cache (using lettuce)</span></span><br><span class="line"><span class="comment"># readonly-redis -&gt; use redis as level 2 cache ,but never write data to it. if use this provider, you must uncomment `j2cache.L2.config_section` to make the redis configurations available.</span></span><br><span class="line"><span class="comment"># memcached -&gt; use memcached as level 2 cache (xmemcached),</span></span><br><span class="line"><span class="comment"># [classname] -&gt; use custom provider</span></span><br><span class="line"><span class="comment">#########################################</span></span><br><span class="line"></span><br><span class="line"><span class="attr">j2cache.L1.provider_class</span> = <span class="string">caffeine</span></span><br><span class="line"><span class="attr">j2cache.L2.provider_class</span> = <span class="string">redis</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment"># When L2 provider isn&#x27;t `redis`, using `L2.config_section = redis` to read redis configurations</span></span><br><span class="line"><span class="comment"># j2cache.L2.config_section = redis</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment"># Enable/Disable ttl in redis cache data (if disabled, the object in redis will never expire, default:true)</span></span><br><span class="line"><span class="comment"># NOTICE: redis hash mode (redis.storage = hash) do not support this feature)</span></span><br><span class="line"><span class="attr">j2cache.sync_ttl_to_redis</span> = <span class="string">true</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment"># Whether to cache null objects by default (default false)</span></span><br><span class="line"><span class="attr">j2cache.default_cache_null_object</span> = <span class="string">true</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">#########################################</span></span><br><span class="line"><span class="comment"># Cache Serialization Provider</span></span><br><span class="line"><span class="comment"># values:</span></span><br><span class="line"><span class="comment"># fst -&gt; using fast-serialization (recommend)</span></span><br><span class="line"><span class="comment"># kryo -&gt; using kryo serialization</span></span><br><span class="line"><span class="comment"># json -&gt; using fst&#x27;s json serialization (testing)</span></span><br><span class="line"><span class="comment"># fastjson -&gt; using fastjson serialization (embed non-static class not support)</span></span><br><span class="line"><span class="comment"># java -&gt; java standard</span></span><br><span class="line"><span class="comment"># fse -&gt; using fse serialization</span></span><br><span class="line"><span class="comment"># [classname implements Serializer]</span></span><br><span class="line"><span class="comment">#########################################</span></span><br><span class="line"></span><br><span class="line"><span class="attr">j2cache.serialization</span> = <span class="string">json</span></span><br><span class="line"><span class="comment">#json.map.person = net.oschina.j2cache.demo.Person</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">#########################################</span></span><br><span class="line"><span class="comment"># Ehcache configuration</span></span><br><span class="line"><span class="comment">#########################################</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment"># ehcache.configXml = /ehcache.xml</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment"># ehcache3.configXml = /ehcache3.xml</span></span><br><span class="line"><span class="comment"># ehcache3.defaultHeapSize = 1000</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">#########################################</span></span><br><span class="line"><span class="comment"># Caffeine configuration</span></span><br><span class="line"><span class="comment"># caffeine.region.[name] = size, xxxx[s|m|h|d]</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment">#########################################</span></span><br><span class="line"><span class="attr">caffeine.properties</span> = <span class="string">/caffeine.properties</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">#########################################</span></span><br><span class="line"><span class="comment"># Redis connection configuration</span></span><br><span class="line"><span class="comment">#########################################</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">#########################################</span></span><br><span class="line"><span class="comment"># Redis Cluster Mode</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># single -&gt; single redis server</span></span><br><span class="line"><span class="comment"># sentinel -&gt; master-slaves servers</span></span><br><span class="line"><span class="comment"># cluster -&gt; cluster servers (数据库配置无效，使用 database = 0）</span></span><br><span class="line"><span class="comment"># sharded -&gt; sharded servers  (密码、数据库必须在 hosts 中指定，且连接池配置无效 ; redis://user:password@127.0.0.1:6379/0）</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment">#########################################</span></span><br><span class="line"></span><br><span class="line"><span class="attr">redis.mode</span> = <span class="string">single</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">#redis storage mode (generic|hash)</span></span><br><span class="line"><span class="attr">redis.storage</span> = <span class="string">generic</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">## redis pub/sub channel name</span></span><br><span class="line"><span class="attr">redis.channel</span> = <span class="string">j2cache</span></span><br><span class="line"><span class="comment">## redis pub/sub server (using redis.hosts when empty)</span></span><br><span class="line"><span class="attr">redis.channel.host</span> =<span class="string"></span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">#cluster name just for sharded</span></span><br><span class="line"><span class="attr">redis.cluster_name</span> = <span class="string">j2cache</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">## redis cache namespace optional, default[empty]</span></span><br><span class="line"><span class="attr">redis.namespace</span> =<span class="string"></span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">## redis command scan parameter count, default[1000]</span></span><br><span class="line"><span class="comment">#redis.scanCount = 1000</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">## connection</span></span><br><span class="line"><span class="comment"># Separate multiple redis nodes with commas, such as 192.168.0.10:6379,192.168.0.11:6379,192.168.0.12:6379</span></span><br><span class="line"></span><br><span class="line"><span class="attr">redis.hosts</span> = <span class="string">127.0.0.1:6379</span></span><br><span class="line"><span class="attr">redis.timeout</span> = <span class="string">2000</span></span><br><span class="line"><span class="attr">redis.password</span> =<span class="string"></span></span><br><span class="line"><span class="attr">redis.database</span> = <span class="string">0</span></span><br><span class="line"><span class="attr">redis.ssl</span> = <span class="string">false</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">## redis pool properties</span></span><br><span class="line"><span class="attr">redis.maxTotal</span> = <span class="string">100</span></span><br><span class="line"><span class="attr">redis.maxIdle</span> = <span class="string">10</span></span><br><span class="line"><span class="attr">redis.maxWaitMillis</span> = <span class="string">5000</span></span><br><span class="line"><span class="attr">redis.minEvictableIdleTimeMillis</span> = <span class="string">60000</span></span><br><span class="line"><span class="attr">redis.minIdle</span> = <span class="string">1</span></span><br><span class="line"><span class="attr">redis.numTestsPerEvictionRun</span> = <span class="string">10</span></span><br><span class="line"><span class="attr">redis.lifo</span> = <span class="string">false</span></span><br><span class="line"><span class="attr">redis.softMinEvictableIdleTimeMillis</span> = <span class="string">10</span></span><br><span class="line"><span class="attr">redis.testOnBorrow</span> = <span class="string">true</span></span><br><span class="line"><span class="attr">redis.testOnReturn</span> = <span class="string">false</span></span><br><span class="line"><span class="attr">redis.testWhileIdle</span> = <span class="string">true</span></span><br><span class="line"><span class="attr">redis.timeBetweenEvictionRunsMillis</span> = <span class="string">300000</span></span><br><span class="line"><span class="attr">redis.blockWhenExhausted</span> = <span class="string">false</span></span><br><span class="line"><span class="attr">redis.jmxEnabled</span> = <span class="string">false</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">#########################################</span></span><br><span class="line"><span class="comment"># Lettuce scheme</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># redis -&gt; single redis server</span></span><br><span class="line"><span class="comment"># rediss -&gt; single redis server with ssl</span></span><br><span class="line"><span class="comment"># redis-sentinel -&gt; redis sentinel</span></span><br><span class="line"><span class="comment"># redis-cluster -&gt; cluster servers</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment">#########################################</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">#########################################</span></span><br><span class="line"><span class="comment"># Lettuce Mode</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># single -&gt; single redis server</span></span><br><span class="line"><span class="comment"># sentinel -&gt; master-slaves servers</span></span><br><span class="line"><span class="comment"># cluster -&gt; cluster servers (数据库配置无效，使用 database = 0）</span></span><br><span class="line"><span class="comment"># sharded -&gt; sharded servers  (密码、数据库必须在 hosts 中指定，且连接池配置无效 ; redis://user:password@127.0.0.1:6379/0）</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment">#########################################</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">## redis command scan parameter count, default[1000]</span></span><br><span class="line"><span class="comment">#lettuce.scanCount = 1000</span></span><br><span class="line"><span class="attr">lettuce.mode</span> = <span class="string">single</span></span><br><span class="line"><span class="attr">lettuce.namespace</span> =<span class="string"></span></span><br><span class="line"><span class="attr">lettuce.storage</span> = <span class="string">hash</span></span><br><span class="line"><span class="attr">lettuce.channel</span> = <span class="string">j2cache</span></span><br><span class="line"><span class="attr">lettuce.scheme</span> = <span class="string">redis</span></span><br><span class="line"><span class="attr">lettuce.hosts</span> = <span class="string">127.0.0.1:6379</span></span><br><span class="line"><span class="attr">lettuce.password</span> =<span class="string"></span></span><br><span class="line"><span class="attr">lettuce.database</span> = <span class="string">0</span></span><br><span class="line"><span class="attr">lettuce.sentinelMasterId</span> =<span class="string"></span></span><br><span class="line"><span class="attr">lettuce.maxTotal</span> = <span class="string">100</span></span><br><span class="line"><span class="attr">lettuce.maxIdle</span> = <span class="string">10</span></span><br><span class="line"><span class="attr">lettuce.minIdle</span> = <span class="string">10</span></span><br><span class="line"><span class="comment"># timeout in milliseconds</span></span><br><span class="line"><span class="attr">lettuce.timeout</span> = <span class="string">10000</span></span><br><span class="line"><span class="comment"># redis cluster topology refresh interval in milliseconds</span></span><br><span class="line"><span class="attr">lettuce.clusterTopologyRefresh</span> = <span class="string">3000</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">#########################################</span></span><br><span class="line"><span class="comment"># memcached server configurations</span></span><br><span class="line"><span class="comment"># refer to https://gitee.com/mirrors/XMemcached</span></span><br><span class="line"><span class="comment">#########################################</span></span><br><span class="line"></span><br><span class="line"><span class="attr">memcached.servers</span> = <span class="string">127.0.0.1:11211</span></span><br><span class="line"><span class="attr">memcached.username</span> =<span class="string"></span></span><br><span class="line"><span class="attr">memcached.password</span> =<span class="string"></span></span><br><span class="line"><span class="attr">memcached.connectionPoolSize</span> = <span class="string">10</span></span><br><span class="line"><span class="attr">memcached.connectTimeout</span> = <span class="string">1000</span></span><br><span class="line"><span class="attr">memcached.failureMode</span> = <span class="string">false</span></span><br><span class="line"><span class="attr">memcached.healSessionInterval</span> = <span class="string">1000</span></span><br><span class="line"><span class="attr">memcached.maxQueuedNoReplyOperations</span> = <span class="string">100</span></span><br><span class="line"><span class="attr">memcached.opTimeout</span> = <span class="string">100</span></span><br><span class="line"><span class="attr">memcached.sanitizeKeys</span> = <span class="string">false</span></span><br></pre></td></tr></table></figure>

<h3 id="任务"><a href="#任务" class="headerlink" title="任务"></a>任务</h3><h4 id="Quartz"><a href="#Quartz" class="headerlink" title="Quartz"></a>Quartz</h4><p>相关概念</p>
<ul>
<li>工作(Job):用于定义具体执行的工作</li>
<li>工作明细(JobDetail):用于描述定时工作相关的信息</li>
<li>触发器（Trigger):用于描述触发工作的规则，通常使用cron表达式定义调度规则</li>
<li>调度器(Scheduler):描述了工作明细与触发器的对应关系</li>
</ul>
<p><strong>步骤①</strong>：导入springboot整合Quartz的starter </p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-quartz<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p><strong>步骤②</strong>：定义任务Bean，按照Quartz的开发规范制作，继承QuartzJobBean </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.example.quartz;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> org.quartz.JobExecutionContext;</span><br><span class="line"><span class="keyword">import</span> org.quartz.JobExecutionException;</span><br><span class="line"><span class="keyword">import</span> org.springframework.scheduling.quartz.QuartzJobBean;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.Date;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyQuartz</span> <span class="keyword">extends</span> <span class="title class_">QuartzJobBean</span> &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">executeInternal</span><span class="params">(JobExecutionContext context)</span> <span class="keyword">throws</span> JobExecutionException &#123;</span><br><span class="line">        <span class="type">Date</span> <span class="variable">fireTime</span> <span class="operator">=</span> context.getFireTime();</span><br><span class="line">        System.out.println(<span class="string">&quot;quartz task run...&quot;</span>+fireTime);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>步骤③</strong>：创建Quartz配置类，定义工作明细（JobDetail）与触发器的（Trigger）bean </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.example.config;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.example.quartz.MyQuartz;</span><br><span class="line"><span class="keyword">import</span> org.quartz.*;</span><br><span class="line"><span class="keyword">import</span> org.springframework.context.annotation.Bean;</span><br><span class="line"><span class="keyword">import</span> org.springframework.context.annotation.Configuration;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">QuartzConfig</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="keyword">public</span> JobDetail <span class="title function_">printJobDetail</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">// 绑定具体的工作</span></span><br><span class="line">        <span class="keyword">return</span> JobBuilder.newJob(MyQuartz.class).storeDurably().build();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="keyword">public</span> Trigger <span class="title function_">printTrigger</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="type">ScheduleBuilder</span> <span class="variable">scheduleBuilder</span> <span class="operator">=</span> CronScheduleBuilder.cronSchedule(<span class="string">&quot;0/10 * * * * ?&quot;</span>);</span><br><span class="line">        <span class="comment">// 绑定对应的工作明细</span></span><br><span class="line">        <span class="keyword">return</span> TriggerBuilder.newTrigger().forJob(printJobDetail()).withSchedule(scheduleBuilder).build();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>工作明细中要设置对应的具体工作，使用newJob()操作传入对应的工作任务类型即可。</p>
<p>触发器需要绑定任务，使用forJob()操作传入绑定的工作明细对象。此处可以为工作明细设置名称然后使用名称绑定，也可以直接调用对应方法绑定。触发器中最核心的规则是执行时间，此处使用调度器定义执行时间，执行时间描述方式使用的是<strong>cron表达式</strong>。</p>
<h4 id="Task"><a href="#Task" class="headerlink" title="Task"></a>Task</h4><p><strong>步骤①</strong>：开启定时任务功能，在引导类上开启定时任务功能的开关，使用注解@EnableScheduling </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@SpringBootApplication</span></span><br><span class="line"><span class="meta">@EnableScheduling</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Springboot09TaskApplication</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        SpringApplication.run(Springboot09TaskApplication.class, args);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>步骤②</strong>：定义Bean，在对应要定时执行的操作上方，使用注解@Scheduled定义执行的时间，执行时间的描述方式还是cron表达式 </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyBean</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Scheduled(cron = &quot;0/5 * * * * ?&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">print</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(Thread.currentThread().getName()+<span class="string">&quot;MyBean spring task run...&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>如何想对定时任务进行相关配置，可以通过配置文件进行 </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">spring:</span><br><span class="line">  task:</span><br><span class="line">    scheduling:</span><br><span class="line">      # 任务调度线程池大小 默认<span class="number">1</span></span><br><span class="line">      pool:</span><br><span class="line">        size: <span class="number">1</span></span><br><span class="line">      # 调度线程名称前缀 默认 scheduling-</span><br><span class="line">      thread-name-prefix: sch_</span><br><span class="line">      shutdown:</span><br><span class="line">        # 线程池关闭时等待所有任务完成</span><br><span class="line">        await-termination: <span class="literal">false</span></span><br><span class="line">        # 调度线程关闭前最大等待时间，确保最后一定关闭</span><br><span class="line">        await-termination-period: 10s</span><br></pre></td></tr></table></figure>

<h3 id="邮件"><a href="#邮件" class="headerlink" title="邮件"></a>邮件</h3><ul>
<li>SMTP（Simple Mail Transfer Protocol）：简单邮件传输协议，用于<strong>发送</strong>电子邮件的传输协议</li>
<li>POP3（Post Office Protocol - Version 3）：用于<strong>接收</strong>电子邮件的标准协议</li>
<li>IMAP（Internet Mail Access Protocol）：互联网消息协议，是POP3的替代协议</li>
</ul>
<p>简单说就是SMPT是发邮件的标准，POP3是收邮件的标准，IMAP是对POP3的升级。</p>
<h4 id="发送简单邮件"><a href="#发送简单邮件" class="headerlink" title="发送简单邮件"></a>发送简单邮件</h4><p><strong>步骤①</strong>：导入springboot整合javamail的starter </p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-mail<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p><strong>步骤②</strong>：配置邮箱的登录信息 </p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">mail:</span></span><br><span class="line">    <span class="attr">host:</span> <span class="string">smtp.163.com</span></span><br><span class="line">    <span class="attr">username:</span> <span class="string">x******6@163.com</span></span><br><span class="line">    <span class="attr">password:</span> <span class="string">Z*******S</span> <span class="comment"># 授权码</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p><strong>步骤③</strong>：使用JavaMailSender接口发送邮件 </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.example.service.impl;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.example.service.SendMailService;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.mail.SimpleMailMessage;</span><br><span class="line"><span class="keyword">import</span> org.springframework.mail.javamail.JavaMailSender;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Service;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SendMailServiceImpl</span> <span class="keyword">implements</span> <span class="title class_">SendMailService</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> JavaMailSender javaMailSender;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 发送人</span></span><br><span class="line">    <span class="keyword">private</span> <span class="type">String</span> <span class="variable">from</span> <span class="operator">=</span> <span class="string">&quot;xlr20031006@163.com&quot;</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 接收人</span></span><br><span class="line">    <span class="keyword">private</span> <span class="type">String</span> <span class="variable">to</span> <span class="operator">=</span> <span class="string">&quot;3451246424@qq.com&quot;</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 标题</span></span><br><span class="line">    <span class="keyword">private</span> <span class="type">String</span> <span class="variable">subject</span> <span class="operator">=</span> <span class="string">&quot;Test&quot;</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 正文</span></span><br><span class="line">    <span class="keyword">private</span> <span class="type">String</span> <span class="variable">text</span> <span class="operator">=</span> <span class="string">&quot;A test&quot;</span>;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">sendMail</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="type">SimpleMailMessage</span> <span class="variable">message</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">SimpleMailMessage</span>();</span><br><span class="line">        message.setFrom(from+<span class="string">&quot;(X)&quot;</span>);</span><br><span class="line">        message.setTo(to);</span><br><span class="line">        message.setSubject(subject);</span><br><span class="line">        message.setText(text);</span><br><span class="line">        javaMailSender.send(message);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>将发送邮件的必要信息（发件人、收件人、标题、正文）封装到SimpleMailMessage对象中，可以根据规则设置发送人昵称等。 </p>
<h4 id="发送多组件邮件（附件、复杂正文）"><a href="#发送多组件邮件（附件、复杂正文）" class="headerlink" title="发送多组件邮件（附件、复杂正文）"></a>发送多组件邮件（附件、复杂正文）</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.example.service.impl;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.example.service.SendMailService;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.mail.javamail.JavaMailSender;</span><br><span class="line"><span class="keyword">import</span> org.springframework.mail.javamail.MimeMessageHelper;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Service;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> javax.mail.MessagingException;</span><br><span class="line"><span class="keyword">import</span> javax.mail.internet.MimeMessage;</span><br><span class="line"><span class="keyword">import</span> java.io.File;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SendMailServiceImpl2</span> <span class="keyword">implements</span> <span class="title class_">SendMailService</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> JavaMailSender javaMailSender;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 发送人</span></span><br><span class="line">    <span class="keyword">private</span> <span class="type">String</span> <span class="variable">from</span> <span class="operator">=</span> <span class="string">&quot;xlr20031006@163.com&quot;</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 接收人</span></span><br><span class="line">    <span class="keyword">private</span> <span class="type">String</span> <span class="variable">to</span> <span class="operator">=</span> <span class="string">&quot;3451246424@qq.com&quot;</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 标题</span></span><br><span class="line">    <span class="keyword">private</span> <span class="type">String</span> <span class="variable">subject</span> <span class="operator">=</span> <span class="string">&quot;Test&quot;</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 正文</span></span><br><span class="line">    <span class="keyword">private</span> <span class="type">String</span> <span class="variable">text</span> <span class="operator">=</span> <span class="string">&quot;&lt;img src=&#x27;https://img.zcool.cn/community/01be645af708d0a801207ab4684087.jpg@2o.jpg&#x27;&gt;&lt;/img&gt;&quot;</span> +</span><br><span class="line">            <span class="string">&quot;&lt;a href=&#x27;https://decxlr.github.io/&#x27;&gt;君不见，黄河之水天上来，奔流到海不复回。&lt;/a&gt;&quot;</span>;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">sendMail</span><span class="params">()</span> &#123;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="type">MimeMessage</span> <span class="variable">message</span> <span class="operator">=</span> javaMailSender.createMimeMessage();</span><br><span class="line">            <span class="type">MimeMessageHelper</span> <span class="variable">helper</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MimeMessageHelper</span>(message,<span class="literal">true</span>);</span><br><span class="line">            helper.setFrom(from+<span class="string">&quot;(X)&quot;</span>);</span><br><span class="line">            helper.setTo(to);</span><br><span class="line">            helper.setSubject(subject);</span><br><span class="line">            helper.setText(text,<span class="literal">true</span>);</span><br><span class="line"></span><br><span class="line">            <span class="comment">// 添加附件</span></span><br><span class="line">            <span class="type">File</span> <span class="variable">file1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">File</span>(<span class="string">&quot;src/main/resources/Android使用网络技术.md&quot;</span>);</span><br><span class="line">            <span class="type">File</span> <span class="variable">file2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">File</span>(<span class="string">&quot;src/main/resources/windows-port.png&quot;</span>);</span><br><span class="line"></span><br><span class="line">            helper.addAttachment(file1.getName(),file1);</span><br><span class="line">            helper.addAttachment(<span class="string">&quot;png文件.png&quot;</span>,file2);</span><br><span class="line"></span><br><span class="line">            javaMailSender.send(message);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (MessagingException e) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">RuntimeException</span>(e);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
    </div>

    
    
    

      <footer class="post-footer">
          <div class="post-tags">
              <a href="/xlrblog/tags/Spring/" rel="tag"># Spring</a>
          </div>

        


        
    <div class="post-nav">
      <div class="post-nav-item">
    <a href="/xlrblog/2023/09/02/SpringBoot%E5%AE%9E%E7%94%A8%E7%AF%87/" rel="prev" title="SpringBoot实用篇(多环境，日志，配置，测试)">
      <i class="fa fa-chevron-left"></i> SpringBoot实用篇(多环境，日志，配置，测试)
    </a></div>
      <div class="post-nav-item">
    <a href="/xlrblog/2023/09/05/SpringBoot%E5%AE%9E%E7%94%A8%E7%AF%87-%E6%B6%88%E6%81%AF%EF%BC%8C%E7%9B%91%E6%8E%A7/" rel="next" title="SpringBoot实用篇(消息，监控)">
      SpringBoot实用篇(消息，监控) <i class="fa fa-chevron-right"></i>
    </a></div>
    </div>
      </footer>
    
  </article>
  
  
  



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%95%B0%E6%8D%AE%E5%B1%82%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88"><span class="nav-number">1.</span> <span class="nav-text">数据层解决方案</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#SQL"><span class="nav-number">1.1.</span> <span class="nav-text">SQL</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%95%B0%E6%8D%AE%E6%BA%90%E6%8A%80%E6%9C%AF"><span class="nav-number">1.1.1.</span> <span class="nav-text">数据源技术</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%8C%81%E4%B9%85%E5%8C%96%E6%8A%80%E6%9C%AF"><span class="nav-number">1.1.2.</span> <span class="nav-text">持久化技术</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%95%B0%E6%8D%AE%E5%BA%93%E6%8A%80%E6%9C%AF"><span class="nav-number">1.1.3.</span> <span class="nav-text">数据库技术</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#NoSQL"><span class="nav-number">1.2.</span> <span class="nav-text">NoSQL</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#SpringBoot%E6%95%B4%E5%90%88Redis"><span class="nav-number">1.2.1.</span> <span class="nav-text">SpringBoot整合Redis</span></a><ol class="nav-child"><li class="nav-item nav-level-5"><a class="nav-link" href="#%E5%90%AF%E5%8A%A8%E6%9C%8D%E5%8A%A1%E5%99%A8"><span class="nav-number">1.2.1.1.</span> <span class="nav-text">启动服务器</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#%E5%90%AF%E5%8A%A8%E5%AE%A2%E6%88%B7%E7%AB%AF"><span class="nav-number">1.2.1.2.</span> <span class="nav-text">启动客户端</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#%E5%9F%BA%E6%9C%AC%E6%93%8D%E4%BD%9C"><span class="nav-number">1.2.1.3.</span> <span class="nav-text">基本操作</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#%E6%95%B4%E5%90%88"><span class="nav-number">1.2.1.4.</span> <span class="nav-text">整合</span></a></li></ol></li><li class="nav-item nav-level-4"><a class="nav-link" href="#SpringBoot%E6%95%B4%E5%90%88MongoDB"><span class="nav-number">1.2.2.</span> <span class="nav-text">SpringBoot整合MongoDB</span></a><ol class="nav-child"><li class="nav-item nav-level-5"><a class="nav-link" href="#%E5%90%AF%E5%8A%A8%E6%9C%8D%E5%8A%A1%E5%99%A8-1"><span class="nav-number">1.2.2.1.</span> <span class="nav-text">启动服务器</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#%E5%90%AF%E5%8A%A8%E5%AE%A2%E6%88%B7%E7%AB%AF-1"><span class="nav-number">1.2.2.2.</span> <span class="nav-text">启动客户端</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#%E5%9F%BA%E6%9C%AC%E6%93%8D%E4%BD%9C-1"><span class="nav-number">1.2.2.3.</span> <span class="nav-text">基本操作</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#%E6%95%B4%E5%90%88-1"><span class="nav-number">1.2.2.4.</span> <span class="nav-text">整合</span></a></li></ol></li><li class="nav-item nav-level-4"><a class="nav-link" href="#SpringBoot%E6%95%B4%E5%90%88ES"><span class="nav-number">1.2.3.</span> <span class="nav-text">SpringBoot整合ES</span></a><ol class="nav-child"><li class="nav-item nav-level-5"><a class="nav-link" href="#%E5%AE%89%E8%A3%85"><span class="nav-number">1.2.3.1.</span> <span class="nav-text">安装</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#%E5%90%AF%E5%8A%A8%E6%9C%8D%E5%8A%A1%E5%99%A8-2"><span class="nav-number">1.2.3.2.</span> <span class="nav-text">启动服务器</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#%E5%9F%BA%E6%9C%AC%E6%93%8D%E4%BD%9C-2"><span class="nav-number">1.2.3.3.</span> <span class="nav-text">基本操作</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#%E6%95%B4%E5%90%88-2"><span class="nav-number">1.2.3.4.</span> <span class="nav-text">整合</span></a></li></ol></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%95%B4%E5%90%88%E7%AC%AC%E4%B8%89%E6%96%B9%E6%8A%80%E6%9C%AF"><span class="nav-number">2.</span> <span class="nav-text">整合第三方技术</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%BC%93%E5%AD%98"><span class="nav-number">2.1.</span> <span class="nav-text">缓存</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#SpringBoot%E5%86%85%E7%BD%AE%E7%BC%93%E5%AD%98%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88"><span class="nav-number">2.1.1.</span> <span class="nav-text">SpringBoot内置缓存解决方案</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%89%8B%E6%9C%BA%E9%AA%8C%E8%AF%81%E7%A0%81%E6%A1%88%E4%BE%8B"><span class="nav-number">2.1.2.</span> <span class="nav-text">手机验证码案例</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#SpringBoot%E6%95%B4%E5%90%88Ehcache%E7%BC%93%E5%AD%98"><span class="nav-number">2.1.3.</span> <span class="nav-text">SpringBoot整合Ehcache缓存</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#SpringBoot%E6%95%B4%E5%90%88Redis%E7%BC%93%E5%AD%98"><span class="nav-number">2.1.4.</span> <span class="nav-text">SpringBoot整合Redis缓存</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#SpringBoot%E6%95%B4%E5%90%88Memcached%E7%BC%93%E5%AD%98"><span class="nav-number">2.1.5.</span> <span class="nav-text">SpringBoot整合Memcached缓存</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#SpringBoot%E6%95%B4%E5%90%88jetcache%E7%BC%93%E5%AD%98"><span class="nav-number">2.1.6.</span> <span class="nav-text">SpringBoot整合jetcache缓存</span></a><ol class="nav-child"><li class="nav-item nav-level-5"><a class="nav-link" href="#%E7%BA%AF%E8%BF%9C%E7%A8%8B%E6%96%B9%E6%A1%88"><span class="nav-number">2.1.6.1.</span> <span class="nav-text">纯远程方案</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#%E7%BA%AF%E6%9C%AC%E5%9C%B0%E6%96%B9%E6%A1%88"><span class="nav-number">2.1.6.2.</span> <span class="nav-text">纯本地方案</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#%E6%9C%AC%E5%9C%B0-%E8%BF%9C%E7%A8%8B%E6%96%B9%E6%A1%88"><span class="nav-number">2.1.6.3.</span> <span class="nav-text">本地+远程方案</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#jetcache%E7%9A%84%E4%B8%80%E4%BA%9B%E9%85%8D%E7%BD%AE"><span class="nav-number">2.1.6.4.</span> <span class="nav-text">jetcache的一些配置</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#%E6%96%B9%E6%B3%95%E7%BC%93%E5%AD%98"><span class="nav-number">2.1.6.5.</span> <span class="nav-text">方法缓存</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#%E8%BF%9C%E7%A8%8B%E6%96%B9%E6%A1%88%E7%9A%84%E6%95%B0%E6%8D%AE%E5%90%8C%E6%AD%A5"><span class="nav-number">2.1.6.6.</span> <span class="nav-text">远程方案的数据同步</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#%E6%95%B0%E6%8D%AE%E6%8A%A5%E8%A1%A8"><span class="nav-number">2.1.6.7.</span> <span class="nav-text">数据报表</span></a></li></ol></li><li class="nav-item nav-level-4"><a class="nav-link" href="#SpringBoot%E6%95%B4%E5%90%88j2cache%E7%BC%93%E5%AD%98"><span class="nav-number">2.1.7.</span> <span class="nav-text">SpringBoot整合j2cache缓存</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BB%BB%E5%8A%A1"><span class="nav-number">2.2.</span> <span class="nav-text">任务</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#Quartz"><span class="nav-number">2.2.1.</span> <span class="nav-text">Quartz</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#Task"><span class="nav-number">2.2.2.</span> <span class="nav-text">Task</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E9%82%AE%E4%BB%B6"><span class="nav-number">2.3.</span> <span class="nav-text">邮件</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%8F%91%E9%80%81%E7%AE%80%E5%8D%95%E9%82%AE%E4%BB%B6"><span class="nav-number">2.3.1.</span> <span class="nav-text">发送简单邮件</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%8F%91%E9%80%81%E5%A4%9A%E7%BB%84%E4%BB%B6%E9%82%AE%E4%BB%B6%EF%BC%88%E9%99%84%E4%BB%B6%E3%80%81%E5%A4%8D%E6%9D%82%E6%AD%A3%E6%96%87%EF%BC%89"><span class="nav-number">2.3.2.</span> <span class="nav-text">发送多组件邮件（附件、复杂正文）</span></a></li></ol></li></ol></li></ol></div>
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="君不见"
      src="/xlrblog/images/avatar.gif">
  <p class="site-author-name" itemprop="name">君不见</p>
  <div class="site-description" itemprop="description">君不见，黄河之水天上来，奔流到海不复回。</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/xlrblog/archives/">
        
          <span class="site-state-item-count">50</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
        <span class="site-state-item-count">9</span>
        <span class="site-state-item-name">分类</span>
      </div>
      <div class="site-state-item site-state-tags">
        <span class="site-state-item-count">25</span>
        <span class="site-state-item-name">标签</span>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/decxlr" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;decxlr" rel="noopener" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
  </div>



      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2023</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">君不见</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="noopener" target="_blank">Hexo</a> & <a href="https://pisces.theme-next.org/" class="theme-link" rel="noopener" target="_blank">NexT.Pisces</a> 强力驱动
  </div>

        








      </div>
    </footer>
  </div>

  
  <script src="/xlrblog/lib/anime.min.js"></script>
  <script src="/xlrblog/lib/velocity/velocity.min.js"></script>
  <script src="/xlrblog/lib/velocity/velocity.ui.min.js"></script>

<script src="/xlrblog/js/utils.js"></script>

<script src="/xlrblog/js/motion.js"></script>


<script src="/xlrblog/js/schemes/pisces.js"></script>


<script src="/xlrblog/js/next-boot.js"></script>




  




  
<script src="/xlrblog/js/local-search.js"></script>













  

  

</body>
</html>
